Tính toán hàm Carmichael


36

Mô tả công việc

Trong lý thuyết số, hàm Carmichael  λ lấy số nguyên dương  n và trả về số nguyên dương k nhỏ nhất để công suất thứ k của mỗi số nguyên cộng với n bằng 1 modulo n .

Cho một số nguyên dương n , giải pháp của bạn phải tính toán λ (n) . Mã ngắn nhất tính bằng byte thắng.

Về mặt lý thuyết, chương trình của bạn sẽ hoạt động cho các đầu vào lớn tùy ý, nhưng không cần phải hiệu quả.

Lời khuyên

Trình tự của tất cả các λ (n)OEIS A002322 .

Một triển khai Python không được chỉnh sửa sẽ trông giống như

from fractions import gcd

def carmichael(n):
    coprimes = [x for x in range(1, n) if gcd(x, n) == 1]
    k = 1
    while not all(pow(x, k, n) == 1 for x in coprimes):
        k += 1
    return k

(Trong Python, pow(A, B, C)tính toán hiệu quả pow(A, B) % C.)

Các trường hợp thử nghiệm

Input    Output
1        1
2        1
3        2
10       4
35       12
101      100
530      52
3010     84
6511     3056
10000    500

Về mặt lý thuyết có nghĩa là gì? Tôi có thể giả sử rằng đầu vào n vừa với số nguyên 16 bit không? Tôi có thể cho rằng n ^ (n) vừa vặn không?
Dennis

2
Vâng và vâng, tôi muốn nói. Như trong lý thuyết, bao gồm giả vờ các loại bản địa của bạn là chính xác và lớn tùy ý (tôi nghĩ đó là sự đồng thuận, nhưng tôi không chắc chắn).
Lynn

Câu trả lời:



29

Python, 76 73 67 byte

f=lambda n,k=1:1-any(a**-~k*~-a**k%n for a in range(n))or-~f(n,k+1)

Hãy thử trực tuyến!

Một byte nữa có thể được lưu bằng cách trả về True thay vì 1 .

Thực hiện thay thế

Sử dụng cách tiếp cận tương tự, cũng có cách triển khai sau đây của @feersum mà không sử dụng cách hiểu danh sách.

f=lambda n,k=1,a=1:a/n or(a**-~k*~-a**k%n<1)*f(n,k,a+1)or-~f(n,k+1)

Lưu ý rằng việc thực hiện này đòi hỏi thời gian O (n λ (n) ) . Hiệu quả có thể được cải thiện đáng kể trong khi thực sự giảm điểm xuống còn 66 byte , nhưng hàm sẽ trả về True cho đầu vào 2 .

f=lambda n,k=1,a=1:a/n or~-a**k*a**-~k%n<1==f(n,k,a+1)or-~f(n,k+1)

Lý lịch

Định nghĩa và ký hiệu

Tất cả các biến được sử dụng sẽ biểu thị số nguyên; n , kα sẽ biểu thị các số nguyên dương; và p sẽ biểu thị một số nguyên tố dương .

một | b nếu b chia hết cho a , tức là nếu có q sao cho b = qa .

a ≡ b ( mod m) nếu ab có cùng dư lượng modulo m , nghĩa là, nếu m | a - b .

(n)k nhỏ nhất sao cho a k ≡ 1 ( mod n) - tức là sao cho n | a k - 1 - cho tất cả a là nguyên tố cùng với n .

f (n)k nhỏ nhất sao cho a 2k + 1 a k + 1 ( mod n) - tức là sao cho n | a k + 1 (a k - 1) - với mọi a .

λ (n) ≤ f (n)

Khắc phục n và để một số nguyên tố cho n .

Theo định nghĩa của f , n | a f (n) +1 (a f (n) - 1) . Kể từ khi mộtn không có một yếu tố chính thông thường, không phải làm một f (n) +1n , trong đó hàm ý rằng n | một f (n) - 1 .

(n) là số nguyên k nhỏ nhất sao cho n | a k - 1 cho tất cả các số nguyên a tương ứng với n , nó theo đó (n) f (n) .

λ (n) = f (n)

Vì chúng ta đã thiết lập bất đẳng thức λ (n) ≤ f (n) , nên đủ để xác minh rằng k = λ (n) thỏa mãn điều kiện xác định f , tức là n | a λ (n) +1 (a λ (n) - 1) cho tất cả a . Với mục đích này, chúng tôi sẽ thiết lập rằng p α | a λ (n) +1 (a λ (n) - 1) bất cứ khi nào p α | n .

λ (k) | (n) bất cứ khi nào k | n ( nguồn ), vì vậy (a λ (k) - 1) (a λ (n) -λ (k) + a λ (n) -2λ (k) + ⋯ + a λ (k) + 1) = a (n) - 1 và do đó, a (k) - 1 | một λ (n) - 1 | a (n) +1 (a λ (n) - 1) .

Nếu ap α là nguyên tố cùng nhau, theo định nghĩa của λ và ở trên, p α | a λ (p α ) - 1 | a (n) +1 (a λ (n) - 1) theo sau, như mong muốn.

Nếu a = 0 , thì a (n) +1 (a λ (n) - 1) = 0 , chia hết cho tất cả các số nguyên.

Cuối cùng, chúng ta phải xem xét trường hợp ap α có thừa số nguyên tố chung. Vì p là số nguyên tố, điều này hàm ý rằng p | a . Định lý của Carmichael thiết lập rằng λ (p α ) = (p - 1) p α - 1 nếu p> 2 hoặc α <3 và điều đó (p α ) = p α - 2 nếu không. Trong mọi trường hợp, (p α ) p α - 2 2 α - 2 > α - 2 .

Do đó, λ (n) + 1 (p α ) + 1> α - 1 , do đó (n) + 1 ≥ αp α | p λ (n) +1 | một λ (n) +1 | a (n) +1 (a λ (n) - 1) . Điều này hoàn thành bằng chứng.

Làm thế nào nó hoạt động

Mặc dù các định nghĩa của f (n)(n) xem xét tất cả các giá trị có thể có của a , nhưng nó đủ để kiểm tra các giá trị nằm trong [0, ..., n - 1] .

Khi f (n, k) được gọi, nó sẽ tính toán một k + 1 (một k - 1)% n cho tất cả các giá trị của một trong phạm vi đó, đó là 0 khi và chỉ khi n | một k + 1 (một k - 1) .

Nếu tất cả các phần dư được tính bằng 0, k = (n)anytrả về Sai , vì vậy f (n, k) trả về 1 .

Mặt khác, trong khi k <λ (n) , 1-any(...)sẽ trả về 0 , do đó f được gọi đệ quy với giá trị tăng là k . Hàng đầu -~tăng giá trị trả về của f (n, k + 1) , vì vậy chúng tôi thêm 1 vào f (n, (n)) = 1 một lần cho mỗi số nguyên trong [1, ..., λ (n) - 1 ] . Kết quả cuối cùng là do đó (n) .


Bạn có thể lưu ít nhất 4 với đệ quy thay vì hiểu danh sách: f=lambda n,k=1,a=1:a/n or(a**k*~-a**k%n<1)*f(n,k,a+2-n%2)or-~f(n,k+1)(Thêm lại một byte nếu bạn không muốn mất n ** (n) thời gian).
frageum

1
Cảm ơn! Trong khi đó, tôi đã tìm thấy một sự cải tiến cho thuật toán của mình dường như vô hiệu hóa lợi ích của việc đệ quy thay vì sử dụng một sự hiểu biết danh sách.
Dennis

14

Toán học không tích hợp sẵn, 58 57 byte

Cảm ơn Martin Ender vì đã tìm thấy một lỗi, sau đó lưu cho tôi các byte cần thiết để sửa nó!

Nhờ dặm để lưu 1 byte! (có vẻ như là 2 đối với tôi)

Được xây dựng là hoàn toàn tốt ... nhưng đối với những người muốn thực hiện nó mà không sử dụng vũ lực, đây là một công thức cho chức năng của Carmichael:

LCM@@(EulerPhi[#^#2]/If[#==2<#2,2,1]&@@@FactorInteger@#)&

Nếu p là số nguyên tố, hàm Carmichael (p ^ r) bằng φ (p ^ r) = (p - 1) * p ^ (r - 1) - ngoại trừ khi p = 2 và r≥3, trong trường hợp này đó là một nửa, cụ thể là 2 ^ (r-2).

Và nếu hệ số công suất nguyên tố của n bằng p1 ^ r1 * p2 ^ r2 * ..., thì (n) bằng bội số chung nhỏ nhất của {λ (p1 ^ r1), λ (p2 ^ r2), .. .}.

Thời gian chạy là một trong nhiều hơn so với bao thanh toán số nguyên ở vị trí đầu tiên.


You can use EulerPhi to get LCM@@(EulerPhi[#^#2]/If[#==2<#2,2,1]&@@@FactorInteger@#)& for 57 bytes.
miles

@miles độc đáo phát hiện! Tôi đếm 56 byte, bạn có thể kiểm tra không?
Greg Martin

Vâng, đó là 57 byte .
miles

rõ ràng tôi thậm chí còn cố gắng đánh gôn ....: /
Greg Martin

12

Các mẫu được coi là có hại , 246 byte

Fun<Ap<Fun<If<Eq<A<2>,T>,A<1>,And<Eq<Ap<Fun<If<A<1>,Ap<A<0>,Rem<A<2>,A<1>>,A<1>>,A<2>>>,A<1,1>,A<2>>,T>,Sub<Ap<Fun<Rem<If<A<1>,Mul<A<2,1>,Ap<A<0>,Sub<A<1>,T>>>,T>,A<1,2>>>,A<1>>,T>>,Ap<A<0>,Add<A<1>,T>,A<1,1>>,Ap<A<0>,A<1>,Sub<A<2>,T>>>>,T,A<1>>>

Một hàm không tên (không phải là có các hàm được đặt tên).

Đây là một esolang bị lãng quên của tôi, được diễn giải bởi các mẫu khởi tạo trình biên dịch C ++. Với độ sâu mẫu tối đa mặc định là g++, nó có thể làm (35), nhưng không thể làm λ (101) (đánh giá lười biếng làm cho mọi thứ tồi tệ hơn).


10

Haskell, 57 56 bytes

f n=[k|k<-[1..],and[mod(m^k)n<2|m<-[1..n],gcd m n<2]]!!0

8

31
............. ._.
Maltysen

10
I never understand the point of implementing such ridiculously specific built-ins.
Fatalize

31
This is almost an addition to the language specifically made for this challenge. Commit by Lynn 2 days ago, challenge by @Lynn today
edc65

5
@edc65 Not to mention that this built-in is pretty much useless outside this challenge and derivatives of it.
Fatalize

3
Well, the Carmichael function is important in number theory (as the currently top answer reflects), so I wouldn't call it useless.
Greg Martin


6

Ruby, 59 56 bytes

->x{a=1..x
a.detect{|k|a.all?{|y|x.gcd(y)>1||y**k%x<2}}}

5

J, 28 27 bytes

[:*./@(5&p:%2^0=8&|)2^/@p:]

The Carmichael function is λ(n) and the totient function is φ(n).

Sử dụng định nghĩa trong đó λ ( pk) = φ(pk)/2 if p = 2 and k > 2 else φ(pk). Then, for general n = p1k1 p2k2piki, λ(n) = LCM[ λ(p1k1) λ(p2k2) ⋯ λ(piki) ].

Usage

Extra commands used to format multiple input/output.

   f =: [:*./@(5&p:%2^0=8&|)2^/@p:]
   f 530
52
   (,.f"0) 1 2 3 10 35 101 530 3010 6511 10000
    1    1
    2    1
    3    2
   10    4
   35   12
  101  100
  530   52
 3010   84
 6511 3056
10000  500

Explanation

[:*./@(5&p:%2^0=8&|)2^/@p:]  Input: integer n
                          ]  Identity function, get n
                    2   p:   Get a table of prime/exponent values for n
                     ^/@     Raise each prime to its exponent to get the prime powers of n
[:    (            )         Operate on the prime powers
                8&|            Take each modulo 8
              0=               Test if its equal to 0, 1 if true else 0
            2^                 Raise 2 to the power of each
       5&p:                    Apply the totient function to each prime power
           %                   Divide it by the powers of 2
  *./@                       Reduce using LCM and return

This gives the wrong answer for 10000 (1000 instead of the correct 500), and indeed for every multiple of 8. 2 is a peculiar prime, and λ(2^a) = 2^{a-2} (not 2^{a-1}) when a≥3.
Greg Martin

Thanks for catching that, seems I can't even read my own output
miles

đôi khi bạn không cô đơn .... :)
Greg Martin

5

Thật ra, 30 28 25 19 26 bytes

Hàm Carmichael, λ(n)trong đó n = p_0**k_0 * p_1**k_1 * ... * p_a**k_a, được định nghĩa là bội số chung (LCM) ít phổ biến nhất λ(p_i**k_i)cho các lũy thừa cực đại p_i**k_iphân chia thành n. Cho rằng với mọi công suất nguyên tố trừ vị trí của số nguyên tố 2, hàm Carmichael tương đương với hàm tổng của Euler λ(n) == φ(n), chúng ta sử dụng φ(n)thay thế. Đối với trường hợp đặc biệt ở 2**kđâu k ≥ 3, chúng tôi chỉ cần kiểm tra nếu 2**3 = 8chia thànhn ở đầu chương trình không và chia cho 2 nếu có.

Thật không may, trên thực tế hiện tại không có tích hợp LCM, vì vậy tôi đã tạo ra một LCM vũ phu. Gợi ý chơi golf chào mừng. Hãy thử trực tuyến!

;7&Yu@\w`iⁿ▒`M╗2`╜@♀%ΣY`╓N

Ungolfing

         Implicit input n.
;        Duplicate n.
7&       n&7 == n%8.
Yu       Logical NOT and increment. If n%8 == 0, return 2. Else, return 1.
@\       Integer divide n by 2 if n%8==0, by 1 otherwise.
          Thus, we have dealt with the special case where p_i == 2 and e_i >= 3.
w        Full prime factorization of n as a list of [prime, exponent] lists.
`...`M   Map the following function over the prime factorization.
  i        Flatten the array, pushing exponent, then prime to the stack.
  ⁿ▒       totient(pow(prime, exponent)).
╗        Save that list of totients in register 0.
2`...`╓  Get the first two values of n where the following function f(n) is truthy.
         Those two numbers will be 0 and our LCM.
  ╜@       Push the list in register 0 and swap with our n.
  ♀%       Get n mod (every number in the list)
  Σ        Sum the modulos. This sum will be 0, if and only if this number is 0 or LCM.
  Y        Logical NOT, so that we only get a truthy if the sum of modulos is 0.
N        Grab the second number, our LCM. Implicit return.

2
Trên thực tế, tôi không biết làm thế nào bạn làm điều này chỉ trong 19 byte.
Bộ đệm đã đọc

@TheBitByte Với việc sử dụng các nội trang totientgcdnội dung. Điều này sẽ ngắn hơn nếu Trên thực tế có lcmtrực tiếp, nhưng tôi không bận tâm đến điều đó và dù sao nó cũng sẽ loại bỏ tối đa 4 byte.
Sherlock9

1
Khẳng định rằng lcm (* a) = sản phẩm (* a) / gcd (* a) là đúng khi * a là danh sách gồm hai số chính xác; tuy nhiên, nói chung là sai đối với các danh sách dài hơn (ví dụ: if * a là {6,10,15}, nó đưa ra 900 thay vì câu trả lời đúng là 60). [Đối với vấn đề đó, nó sai là * a cũng là một danh sách gồm một số!] Và bạn có thể kiểm tra xem mình có trả lời sai cho hơn một nửa các trường hợp kiểm tra được liệt kê trong OP không.
Greg Martin

@GregMartin Cảm ơn những người đứng đầu. Đã sửa.
Sherlock9

4

JavaScript (ES6), 143 135 byte

Chỉnh sửa: đã lưu 8 byte nhờ Neil

Một triển khai sử dụng lập trình chức năng.

n=>(A=[...Array(n).keys()]).find(k=>k&&!c.some(c=>A.slice(0,k).reduce(y=>y*c%n,1)-1),c=A.filter(x=>(g=(x,y)=>x?g(y%x,x):y)(x,n)==1))||1

Ungolfed và bình luận

n =>                                          // Given a positive integer n:
  (A = [...Array(n).keys()])                  // Build A = [0 ... n-1].
  .find(k =>                                  // Try to find k in [1 ... n-1] such as
    k && !c.some(c =>                         // for each coprime c: c^k ≡ 1 (mod n).
      A.slice(0, k).reduce(y =>               // We use reduce() to compute
        y * c % n, 1                          // c^k mod n.
      ) - 1                                   // Compare it with 1.
    ),                                        // The list of coprimes is precomputed
    c = A.filter(x =>                         // before the find() loop is executed:
      (                                       // for each x in [0 ... n-1], keep
        g = (x, y) => x ? g(y % x, x) : y     // only integers that verify:
      )(x, n) == 1                            // gcd(x, n) = 1
    )                                         // (computed recursively)
  ) || 1                                      // Default result is 1 (for n = 1)

Bản giới thiệu

Mặc dù nó hoạt động được 651110000tôi sẽ không đưa chúng vào đây vì nó có xu hướng hơi chậm.

let f =
n=>(A=[...Array(n).keys()]).find(k=>k&&!c.some(c=>A.slice(0,k).reduce(y=>y*c%n,1)-1),c=A.filter(x=>(g=(x,y)=>x?g(y%x,x):y)(x,n)==1))||1

console.log(f(1));     // 1
console.log(f(2));     // 1
console.log(f(3));     // 2
console.log(f(10));    // 4
console.log(f(35));    // 12
console.log(f(101));   // 100
console.log(f(530));   // 52
console.log(f(3010));  // 84


1
JS có thể thực hiện 0..n-1phạm vi khá dễ dàng : [...Array(n).keys()]. Điều này đòi hỏi không phải một mà là hai trường hợp đặc biệt nhưng tôi vẫn ở phía trước:n=>(a=[...Array(n).keys()]).find(k=>k&&!c.some(c=>a.slice(0,k).reduce(y=>y*c%n,1)-1),c=a.filter(x=>(g=(x,y)=>x?g(y%x,x):y)(x,n)==1))||1
Neil

2

Ruby, 101 86 91 90 byte

Một cổng Ruby của câu trả lời thực sự của tôi . Gợi ý chơi golf chào mừng.

Chỉnh sửa: -4 byte khi xóa anhưng +9 byte khỏi sửa lỗi được 1trả về nil. -1 byte nhờ Cyoce.

require'prime'
->n{((n%8<1?n/2:n).prime_division<<[2,1]).map{|x,y|x**~-y*~-x}.reduce :lcm}

Ungolfing

require 'prime'
def carmichael(n)
  if n%8 < 1
    n /= 2
  end
  a = []
  n.prime_division.do each |x,y|
    a << x**(y-1)*(x-1)
  end
  return a.reduce :lcm
end

Bạn không cần a=. Thật không may, bạn quay lại nilvới n = 1 :(. (n.prime_division<<[2,1])Khắc phục điều đó. Không chắc chắn nếu có cách chơi gôn.
m-chrzan

(n%8<1?n/2:n).prime_division...tiết kiệm thêm 2 byte.
m-chrzan

@ m-chrzan alà tàn dư của một nỗ lực chơi gôn trước đó. Cảm ơn đã nhắc nhở về avà cho lên trên 1.
Sherlock9

Bạn có thể lưu một byte bằng cách sử dụng .reduce :lcmthay vì .reduce(:lcm).
Cyoce

1

JavaScript (ES 2016) 149

Việc triển khai tham chiếu Python được chuyển sang JS. Một số dựng sẵn Pyhton lạ mắt bị thiếu trong js, nhưgcdpow, và việc hiểu mảng không phải là tiêu chuẩn trong ES 6. Điều này hoạt động trong Firefox.

n=>eval('for(g=(a,b)=>b?g(b,a%b):a,p=(a,b,c)=>eval("for(r=1;b--;)r=r*a%c"),c=[for(_ of Array(i=n))if(g(i--,n)<2)i+1],k=1;c.some(x=>p(x,k,n)-1);)++k')

Ít chơi gôn

n=>{
  g=(a,b)=>b?g(b,a%b):a
  p=(a,b,c)=>{ 
    for(r=1;b--;)
      r=r*a%c
    return r
  }
  c=[for(_ of Array(i=n)) if(g(i--,n)<2) i+1]
  for(k=1;c.some(x=>p(x,k,n)-1);)
    ++k
  return k
} 

modpow đệ quy ngắn hơn:p=(a,b,c)=>b?a*p(a,b-1,c)%c:1;
Olivier Grégoire

1

Java, 209 207 202 194 192 byte

Mã (96 byte):

n->{for(int x,k=1,a;;k++){for(a=1,x=0;++x<=n&&a<2;)a=g(x,n)<2?p(x,k,n):1;if(a<2||n<2)return k;}}

các hàm bổ sung (96 byte):

int g(int a,int b){return b<1?a:g(b,a%b);}int p(int n,int p,int m){return p<2?n:n*p(n,p-1,m)%m;}

Kiểm tra & không có kế hoạch

import java.util.Arrays;
import java.util.function.IntUnaryOperator;

public class Main2 {

  static int g(int a,int b) { // recursive gcd
    return b < 1
        ? a
        : g(b,a%b);
  }

  static int p(int n, int p, int m) { // recursive modpow
    return p < 2
      ? n
      : n * p(n, p - 1, m) % m;
  }

  public static void main(String[] args) {

    IntUnaryOperator f = n -> {
      for(int x,k=1,a;;k++) { // for each k
        for(a=1,x=0;++x<=n&&a<2;) // for each x
          a=g(x,n)<2?p(x,k,n):1; // compute modpow(x,k,n) if g(x,n)
        if(a<2||n<2) // if all modpow(x,k,n)=1. Also check for weird result for n=1.
          return k;
      }
    };

    Arrays.stream(new int[]{1, 2, 3, 10, 35, 101, 530, 3010, 6511, 10000})
        .map(f)
        .forEach(System.out::println);
  }
}

Ghi chú

  • việc sử dụng alà một intngắn hơn so với nếu tôi phải sử dụng một booleanđể thực hiện các bài kiểm tra của mình.
  • Có, nó ngắn hơn valueOftất cả mới BigIntegerhơn là tạo một hàm riêng biệt (có 5, cộng với ONEhằng số là một phần mềm miễn phí).
  • Thuật toán khác với thuật toán @Master_ex ', vì vậy nó không chỉ là một repost được đánh gôn. Ngoài ra, thuật toán này kém hiệu quả hơn nhiều khi gcdđược tính toán lặp đi lặp lại cho cùng các giá trị.

Dao cạo

  1. 209 -> 207 byte:
    • if(...)a=...; -> a=...?...:1;
    • a==1 -> a<2
  2. 207 -> 202 byte
    • Loại bỏ BigIntegerbằng cách chơi golf gcdmodPowcho int.
  3. 202 -> 194 byte
    • lặp modPow-> đệ quy
  4. 194 -> 192 byte
    • ==1-> <2(dường như hoạt động cho tất cả các trường hợp thử nghiệm, không biết cho các số khác.)

Chào! Tôi đã nhận thấy rằng đầu ra không như mong đợi. Xem câu hỏi cho kết quả mong đợi. Cá nhân, tôi thường viết bài kiểm tra đơn vị trước khi bắt đầu chơi mã của mình, điều đó có ích! Tôi đoán rằng vấn đề có thể là modPow trên các số nguyên, tôi cũng gặp vấn đề này và đó là lý do tại sao tôi đã sử dụng BigInteger vào cuối.
Master_ex

Hmmm ... tôi ngạc nhiên, tôi để các bài kiểm tra của mình chạy ở mọi thay đổi. Tôi sẽ kiểm tra những gì sai.
Olivier Grégoire

1
@Master_ex Tôi đã sửa nó. Quay trở lại phiên bản trước là ok.
Olivier Grégoire

Tôi thấy phương pháp modpow đệ quy của bạn pkhá thông minh. Lúc đầu tôi cũng chỉ cố gắng sử dụng các số nguyên, nhưng như tôi đã đề cập trong câu trả lời của mình, tôi có vấn đề chính xác và đó là lý do tại sao tôi chuyển đến BigInteger(tức là Math.pow(3, 100)%101trả lại 60.0thay vì 1). Việc thực hiện của bạn là miễn dịch với điều này bởi vì nó thực hiện mod trong mỗi lần lặp. Tuy nhiên, nó vẫn bị một lỗi. Đối với lớn m pvẫn có thể trả lại kết quả sai. Ngoài ra, do đệ quy, StackOverflowErrorcó thể dễ dàng xảy ra đối với đầu vào lớn với kích thước ngăn xếp mặc định.
Master_ex

@Master_ex Vâng, đó là hậu quả của việc hạn chế intcác loại. Tôi có thể sử dụng longs thay vì ints, đó là 8 byte thêm. Nhưng theo quan điểm của tôi, tất cả các trường hợp thử nghiệm đều hợp lệ nên tôi để nó như thế. StackOverflowErrorcó thể xảy ra, nhưng đó là cách đệ quy hoạt động. Các phương thức tồn tại để giới hạn ở 32 ngăn xếp, nhưng chúng sử dụng nhiều byte hơn. Việc thực hiện này rất mong manh, vâng, bạn hoàn toàn đúng. Nhưng nó đủ mạnh cho các trường hợp thử nghiệm.
Olivier Grégoire

1

Java8 38 19 + 287 295 253 248 241 = 325 333 272 267 260 byte

BigInteger B(int i){return new BigInteger(""+i);}int c(int...k){int n=k[0];for(k[0]=1;n>1&!java.util.stream.IntStream.range(0,n).filter(i->B(n).gcd(B(i)).equals(B(1))).allMatch(x->B(x).modPow(B(k[0]),B(n)).equals(B(1)));k[0]++);return k[0];}

Nhập khẩu, 19 byte

import java.math.*;

Giải trình

Đó là một thực hiện thẳng về phía trước. Các số nguyên tố được tính theo Set pvà công suất thứ k của mỗi người được sử dụng để kiểm tra xem nó có bằng 1 modulo n không.

Tôi đã phải sử dụng BigIntegervì các vấn đề chính xác.

Sử dụng

public static void main(String[] args) {
    Carmichael c = new Carmichael();
    System.out.println(c.c(3)); // prints 2
}

Ung dung

// returns the BigInteger representation of the given interger
BigInteger B(int i) {
    return new BigInteger(""+i);
}
// for a given integer it returns the result of the carmichael function again as interger
// so the return value cannot be larger
int c(int... k) {
    int n = k[0];
    // iterate k[0] until for all co-primes this is true: (x^n) mod n == 1, if n==1 skip the loop
    for (k[0]=1;n > 1 && !java.util.stream.IntStream.range(0, n)
                .filter(i -> B(n).gcd(B(i)).equals(B(1)))
                .allMatch(x -> B((int) x).modPow(B(k[0]), B(n)).equals(B(1)));k[0]++);
    return k[0];
}

Bất kỳ đề xuất nào để chơi gôn đều được chào đón :-)

Cập nhật

  • Không có yếu tố nào bên ngoài các chức năng giữ trạng thái
  • Làm theo lời khuyên của Olivier Grégoire và lưu 1 byte từ B()
  • Đã xóa k()phương thức và p(đồng nguyên tố) Đặt.
  • Loại bỏ không cần đúc để int.
  • Đã thêm varags và sử dụng thay vì trong khi.

Bạn có thể có một phiên bản chưa được chỉnh sửa (với các bản ngắt dòng, nhận xét ở đây & ở đó, v.v.)
OldBunny2800

@ OldBunny2800: Vâng, chắc chắn rồi. Tuy nhiên, tôi sẽ làm điều đó sau hôm nay vì bây giờ tôi đang bận!
Master_ex

@ OldBunny2800: Tôi đã thêm một phiên bản chưa được chỉnh sửa :-)
Master_ex

Hmmm ... Tôi không chắc đây có phải là chức năng hay chương trình không. Nếu đó là một hàm, có các phần tử bên ngoài nó giữ trạng thái, biến nó thành một phương thức thực tế (hàm là đầu vào thuần túy -> đầu ra không có trạng thái bên ngoài), nếu đó là một chương trình, toàn bộ phương thức chính bị thiếu. Nếu cách giải thích của tôi không chính xác, xin vui lòng cho tôi biết như vậy! Tôi nghĩ sẽ tốt hơn nếu đưa k(int)vào vòng lặp vì nó là một lớp lót và có thể được thực hiện. Thêm vào đó, hằng số O cũng có thể được đặt trong cphương thức. Tôi đoán bạn sẽ giành được byte bằng cách làm như vậy!
Olivier Grégoire

Cụ thể, while(n>1&&!p.stream().allMatch(x->B((int)x).modPow(B(k), B(n)).equals(O)))cạo byte sửa các vấn đề tôi đã đề cập nếu bạn đặt tập hợp và hằng số trở lại phương thức. Ngoài ra, bạn sử dụngO hai lần, thay thế bằng cách B(1)cạo byte.
Olivier Grégoire



0

Vợt 218 byte

(λ(n)(let((fl #f)(cl(for/list((i n) #:when(coprime? n i))i)))(for/sum((k(range 1 n))#:break fl)(set! fl #t)
(for((i(length cl))#:break(not fl))(when(not(= 1(modulo(expt(list-ref cl i)k)n)))(set! fl #f)))(if fl k 0))))

Phiên bản bị đánh cắp:

(require math)
(define f
  (λ(n)
    (let ((fl #f)
          (cl (for/list ((i n) #:when (coprime? n i))
                i)))
             (for/sum ((k (range 1 n)) #:break fl)
               (set! fl #t)
               (for ((i (length cl)) #:break (not fl))
                 (when (not (= 1 (modulo (expt (list-ref cl i) k) n)))
                   (set! fl #f)))
               (if fl k 0)))))

Kiểm tra:

(f 2) 
(f 3)
(f 10)
(f 35)
(f 101)
(f 530)
(f 3010)
(f 6511)
(f 10000)

Đầu ra:

1
2
4
12
100
52
84
3056
500

0

C, 278 276 272 265 256 243 140 134 125 byte

k,x,a,b,t,d;l(n){for(k=d=1;d;)for(d=x=0;++x<n;d=a<2&t>1?k++:d){for(a=x,b=n;t=b;a=t)b=a%b;for(t=1,b=k;b--;t=t*x%n);}return k;}

Điều này sử dụng thuật toán lũy thừa mô-đun chậm, tính toán GCD quá thường xuyên và không còn rò rỉ bộ nhớ!

Ung dung:

int gcd( int a, int b ) {
  int t;
  while( b ) {
    t = b;
    b = a%b;
    a = t;
  }
  return a;
}
int pw(int a,int b,int c){
  int t=1;
  for( int e=0; e<b; e++ ) {
    t=(t*a)%c;
  }
  return t;
}
int carmichael(int n) {
  int k = 1;
  for( ;; ) {
    int done = 1;
    for( int x=1; x<n; x++ ) {
      if( gcd(x,n)==1 && pw(x,k,n) != 1 ) {
        done = 0;
        k++;
      }
    }
    if( done ) break;
  }
  return k;
}

Hãy thử nó trên Ideone


0

Tiên đề 129 byte

c(n)==(r:=[x for x in 1..n|gcd(x,n)=1];(v,k):=(1,1);repeat(for a in r repeat(v:=powmod(a,k,n);v~=1=>break);v<=1=>break;k:=k+1);k)

ít chơi gôn

cml(n)==
 r:=[x for x in 1..n|gcd(x,n)=1];(v,k):=(1,1)
 repeat 
   for a in r repeat(v:=powmod(a,k,n);v~=1=>break)
   v<=1=>break
   k:=k+1
 k

các kết quả

(3) -> [i,c(i)] for i in [1,2,3,10,35,101,530,3010,6511,10000]
   Compiling function c with type PositiveInteger -> PositiveInteger

   (3)
   [[1,1], [2,1], [3,2], [10,4], [35,12], [101,100], [530,52], [3010,84],
    [6511,3056], [10000,500]]
                                             Type: Tuple List PositiveInteger
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.