计算Carmichael函数


36

任务描述

在数论中,Carmichael的函数 λ取正整数  Ñ并返回最小正整数ķ使得ķ的每个整数次幂互质Ñ等于1个模Ñ

给定正整数n,您的解决方案必须计算λ(n)。以字节为单位的最短代码获胜。

从理论上讲,您的程序应该可以为任意大的输入工作,但是并不需要高效。

提示

所有λ(n)的序列为OEIS A002322

非高尔夫的Python实现看起来像

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

(在Python中,pow(A, B, C)有效地进行计算pow(A, B) % C。)

测试用例

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

理论上这是什么意思?我可以假定输入n可以容纳16位整数吗?我是否可以假设n ^λ(n)符合双精度?
丹尼斯

2
是的,是的,我会说。如,在理论上包括假装你的本机类型有任意精确和大(我认为这是共识,但我不知道)。
林恩

Answers:



29

Python,76 73 67字节

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

在线尝试!

通过返回True而不是1可以保存另一个字节。

替代实施

使用相同的方法,@feersum还有以下实现,它不使用列表推导。

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)

请注意,此实现需要O(nλ(n)时间。效率可以大大提高,而实际上将分数降低66个字节,但是该函数将为输入2返回True

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)

背景

定义和符号

所有使用的变量将表示整数;nkα表示整数;和p会表示了积极的总理

一个| b如果b是整除一个,即,如果有q使得B = QA

一个≡B(MOD M)如果一个b具有相同的残基模,即,如果M | a-b

λ(N)是最小ķ使得一个ķ ≡1(MOD N) -即,使得N | 一个ķ - 1 -对于所有一个是互质Ñ

F(N)是最小ķ使得一个2K + 1 ≡一个K + 1MOD N) -即,使得N | a k + 1(a k -1) –对于所有a

λ(n)≤f(n)

修复n并将a设为n的互质。

根据f的定义,n | a f(n)+1(a f(n) -1)。由于一个ñ没有一个共同的主要因素,无论是做一个F(N)+1ñ,这意味着N | 一个f(n) -1

由于λ(n)是最小整数k,因此n | n 对于与n互质的所有整数a k -1,得出λ(n)≤f(n)

λ(n)= f(n)

由于我们已经建立了不等式λ(n)≤f(n),因此足以验证k =λ(n)满足定义f的条件,即n | 一个λ(n)的1(一个λ(N) - 1)对于所有一个。为此,我们将建立p α | 一个λ(n)的1(一个λ(N) - 1)每当p α | n

λ(k)| λ(n)每当k | Ñ),因此(A λ(k)的 - 1)(一个λ(N)-λ(k)的 +一个λ(N)-2λ(K) +⋯+一个λ(k)的 + 1)=一λ(N) - 1,因此,一个λ(k)的 - 1 | 一个λ(N) - 1 | 一个λ(n)的1(一个λ(N) - 1)

如果一个p α是互质,通过定义λ和上述中,p α | 一个λ(P α - 1 | 根据需要跟随一个λ(n)+1aλ(n) -1)

如果α= 0,则λ(n)的1(一个λ(N) - 1)= 0,这是通过所有整数整除。

最后,我们必须考虑这样的情况p α都有一个共同的主要因素。由于p为素数,这意味着P | 一个卡迈克尔定理确定,如果p> 2α<3,则λ()=(p-1)pα-1,否则,λ()= pα-2。在所有情况下,λ()≥pα - 2≥2α -2 >α-2

因此,λ(N)+ 1≥λ(P α)+ 1>α - 1,因此λ(N)+ 1≥αp α | p λ(N)+1 | 一个λ(N)+1 | 一个λ(n)的1(一个λ(N) - 1) 。这样就完成了证明。

怎么运行的

尽管f(n)λ(n)的定义考虑了a的所有可能值,但足以测试[0,...,n-1]中的值

F(N,K)被调用时,它计算一个K + 1(一个ķ - 1)%N为的所有值一个在该范围内,这是0,当且仅当N | a k + 1(a k -1)

如果所有计算的残差均为零,则k =λ(n)any返回False,因此f(n,k)返回1

另一方面,当k <λ(n)时1-any(...)将返回0,因此f以递增的值k递归调用。前导-~使f(n,k + 1)的返回值递增,因此对于[1,...,λ(n)-1中的每个整数,我们将1加到f(n,λ(n))= 1一次]。因此,最终结果为λ(n)


您可以使用递归而不是列表解析来保存至少4个:(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)如果不希望花费n **λ(n)的时间,则添加一个字节)。
feersum

1
谢谢!同时,我发现我的算法得到了改进,似乎使递归而不是使用列表推导的好处无效了。
丹尼斯

14

没有内置的Mathematica,58 57字节

感谢Martin Ender发现错误,然后为我保存了修复它所需的字节!

感谢Miles节省1个字节!(对我来说好像是2)

内建函数很好...但是对于那些想要在不使用暴力的情况下实现它的人来说,这是Carmichael函数的公式:

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

如果p是素数,则Carmichael函数λ(p ^ r)等于φ(p ^ r)=(p-1)* p ^(r-1),除非 p = 2和r≥3,在这种情况下一半,即2 ^(r-2)。

并且如果n的素数功率因式分解等于p1 ^ r1 * p2 ^ r2 * ...,则λ(n)等于{λ(p1 ^ r1),λ(p2 ^ r2),.. }。

运行时比首先考虑整数要多一刻。


您可以使用EulerPhi获取LCM@@(EulerPhi[#^#2]/If[#==2<#2,2,1]&@@@FactorInteger@#)&57个字节。
英里

发现了@miles!我数了56个字节,可以检查吗?
格雷格·马丁

是的,这是57 个字节
英里

显然,我什至试图打高尔夫球。...:/
Greg Martin

12

认为有害的模板,246个字节

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>>>

未命名的函数(不是有命名函数)。

这是我的一个被遗忘的方法,由C ++编译器实例化模板解释。在默认的最大模板深度为的情况下g++,它可以执行λ(35),但不能执行λ(101)(惰性评估会使情况更糟)。


10

Haskell,57 56字节

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

8

果冻,2个字节

Æc

谢谢你的内置@Lynn


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

10
我从来不理解实现如此可笑的特定内置程序的意义。
致命

31
几乎是为应对这一挑战而专门设计的语言的补充。Lynn 2天前提交,今天
@Lynn

5
@ edc65更不用说此内置函数在此挑战及其派生类之外几乎没有用。
致命

3
好吧,Carmichael函数在数论中很重要(正如当前的最佳答案所反映的那样),所以我不会称它为无用的。
格雷格·马丁


6

红宝石, 59 56个字节

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

5

J,28 27字节

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

Carmichael函数为λ(n),上位函数为φ(n)。

如果p = 2且k > 2否则使用φ(p k)= λ(p k)=φ(p k)/ 2的定义。然后,对于一般的n = p 1 k 1 p 2 k 2p i k i,λ(n)= LCM [λ(p 1 k 1)λ(p 2 k 2)⋯λ(p i k i)] 。

用法

用于格式化多个输入/输出的额外命令。

   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

说明

[:*./@(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

这给出了错误的答案10000(1000而不是正确的500),并且确实是8的每一个倍数。2是一个奇数素数,并且λ(2 ^ a)= 2 ^ {a-2}(不是2 ^ { a-1})时a≥3。
格雷格·马丁

感谢您的接见,似乎我什至无法读取自己的输出
英里

有时您并不孤单。...:)
格雷格·马丁

5

其实30 28 25 19 26字节

Carmichael函数(λ(n)其中n = p_0**k_0 * p_1**k_1 * ... * p_a**k_a)定义为划分λ(p_i**k_i)为的最大素幂的的最小公倍数(LCM)。给定除质数为之外的所有质数幂,我们使用Carmichael函数等效于Euler totient函数Euler 。对于特殊情况下在那里,我们只是检查,如果分成2如果它确实在节目的开始,和鸿沟。p_i**k_in2λ(n) == φ(n)φ(n)2**kk ≥ 32**3 = 8n

不幸的是,实际上目前还没有内置LCM,所以我制作了蛮力的LCM。欢迎打高尔夫球。在线尝试!

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

开球

         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
实际上,我不知道您是如何仅用19个字节来完成此操作的。
缓冲读取

@TheBitByte使用totientgcd内置。如果居然lcm直接拥有它,这会更短一些,但是我不太介意,无论如何最多最多只能敲掉4个字节。
Sherlock16年

1
当* a是正好两个数字的列表时,lcm(* a)= product(* a)/ gcd(* a)的说法成立。但是,对于更长的列表,它通常是错误的(例如:如果* a为{6,10,15},它将给出900,而不是正确的答案60)。[因此,* a同样也是一个数字的列表!]并且您可以检查是否为OP中列出的测试用例的一半以上得到了错误的答案。
格雷格·马丁

@GregMartin感谢您的注意。固定。
Sherlock16年

4

的JavaScript(ES6),143个 135字节

编辑:由于尼尔节省了8个字节

使用函数式编程的实现。

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

取消评论

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)

演示版

尽管它确实适用于651110000,但由于它运行缓慢,因此我不会在此处包括它们。

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可以0..n-1很容易地进行范围调整:[...Array(n).keys()]。这不需要两个特殊情况,但我仍然领先: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字节

我的实际答案的一个Ruby端口。欢迎打高尔夫球。

编辑: -4字节从删除,a但+9字节从修复1返回的错误nil。-1字节感谢Cyoce。

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

开球

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

您不需要a=。不幸的是,返回nil对于n = 1 :(。(n.prime_division<<[2,1])修复了不知道如果有一个golfier方式。
M-chrzan

(n%8<1?n/2:n).prime_division...保存另外2个字节。
m-chrzan '16

@ m-chrzan a是早期高尔夫尝试的残余。感谢您的提醒a和注意1
Sherlock16年

您可以使用.reduce :lcm代替来保存一个字节.reduce(:lcm)
Cyoce

1

JavaScript(ES 2016)149

将Python参考实现移植到JS。js中缺少一些花哨的Pyhton内置函数,例如gcdpow,并且ES 6中的数组理解不是标准的。这在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')

少打高尔夫球

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较短:p=(a,b,c)=>b?a*p(a,b-1,c)%c:1;
奥利维尔·格雷瓜尔

1

Java 209 207 202 194 192字节

代码(96字节):

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;}}

额外功能(96字节):

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;}

测试和取消高尔夫

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);
  }
}

笔记

  • 使用的a是一个int比,如果我不得不使用更短的boolean执行我的测试。
  • 是的,对于valueOf所有新BigInteger功能而言,它比创建单独的函数要短(有5个,而ONE常量是免费赠品)。
  • 算法与@Master_ex的算法不同,因此它不只是打高尔夫球。同样,这种算法的效率要低得多gcd,因为对于相同的值一次又一次地计算。

刮胡子

  1. 209-> 207字节:
    • if(...)a=...; -> a=...?...:1;
    • a==1 -> a<2
  2. 207-> 202字节
    • 摆脱了BigInteger被打高尔夫球gcdmodPow进行int
  3. 202-> 194字节
    • 循环modPow->递归
  4. 194-> 192字节
    • ==1-> <2(似乎适用于所有测试用例,其他数字则不知道。)

嘿! 我注意到输出不是预期的。有关预期结果,请参阅问题。就个人而言,我经常在开始编写代码之前编写单元测试,这很有帮助!我想问题可能是整数上的modPow,我也遇到了这个问题,这就是为什么我在最后使用BigInteger的原因。
Master_ex

嗯...我很惊讶,我让我的测试在每次更改时都运行。我会检查怎么了。
OlivierGrégoire'16

1
@Master_ex我修复了它。返回上一个版本是可以的。
奥利维尔·格雷戈雷16'Sep

我发现您的递归modpow方法p非常聪明。我一开始也尝试仅使用整数,但是正如我在回答中提到的那样,我遇到了精度问题,这就是为什么我移至BigInteger(即Math.pow(3, 100)%101返回60.0而不是1)的原因。您的实现不受此影响,因为它在每次迭代中执行mod。但是,它仍然存在错误。对于大m p可能仍会返回错误的结果。同样,由于递归,StackOverflowError对于具有默认堆栈大小的大型输入,可能很容易发生。
Master_ex

@Master_ex是的,这是int类型限制的结果。我可以使用long而不是ints,这将额外增加8个字节。但是在我看来,所有测试用例都是有效的,所以我就这样保留它。StackOverflowError可能会发生,但是递归就是这样。存在限制为32个堆栈的方法,但是这些方法使用更多的字节。此实现非常脆弱,是的,您是完全正确的。但是对于测试案例来说足够强大了。
奥利维尔·格雷戈雷

1

Java8 38 19 + 287 295 253 248 241 = 325 333 272 267 260个字节

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];}

导入,19字节

import java.math.*;

说明

这是直接的实现。互素数是在中计算的Set p,每个人的k次方用于检查它是否等于1模n。

BigInteger由于精度问题,我不得不使用它。

用法

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

不打高尔夫球

// 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];
}

任何有关打高尔夫球的建议都欢迎:-)

更新资料

  • 功能之外没有任何元素可以保持状态
  • 遵循OlivierGrégoire的建议,并从中保存了1个字节 B()
  • 删除了k()方法和p(互素)Set。
  • 删除不需要的强制转换为int。
  • 添加了varags,并使用for代替while。

您可以使用非高尔夫版本(带有换行符,在此处和此处进行评论等)
吗?

@ OldBunny2800:是的,当然。但是,我今天晚些时候再做,因为现在我很忙!
Master_ex

@ OldBunny2800:我添加了一个非高尔夫版本:-)
Master_ex

嗯...我不确定这算不算什么,因为它既不是函数也不是程序。如果它是一个函数,那么它外面的某些元素会保持状态,从而使其成为事实上的方法(函数是纯输入->输出而没有外部状态),如果它是一个程序,则会缺少整个main方法。如果我的解释不正确,请告诉我!我认为最好将其包含k(int)在循环中,因为它是单行的并且可以完成。另外,常数O也可以放在该c方法中。我想您这样做会赢得字节!
OlivierGrégoire16年

具体来说,如果将集合和常量放回方法中,则可以while(n>1&&!p.stream().allMatch(x->B((int)x).modPow(B(k), B(n)).equals(O)))剃除字节修复我提到的问题。此外,您使用O两次,替换为B(1)以剃除字节。
OlivierGrégoire16年

1

Java中,165个163 158 152 143字节

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

我的C实现的另一个端口。

在Ideone上尝试


1

C ++,208200149144140134字节

[](int n){int k=1,x,a,b,t,d=1;for(;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;};

我的C实现的移植。

在Ideone上尝试


0

拍框218字节

(λ(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))))

非高尔夫版本:

(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)))))

测试:

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

输出:

1
2
4
12
100
52
84
3056
500

0

C,278276272265265243140134125字节

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;}

这使用了缓慢的模块化幂运算算法,过于频繁地计算GCD,而不再泄漏内存!

取消高尔夫:

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;
}

在Ideone上尝试


0

公理129字节

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)

少打高尔夫球

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

结果

(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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.