【问题标题】:Calculate n where a^n mod m = 1?计算 n 其中 a^n mod m = 1?
【发布时间】:2013-10-22 18:53:01
【问题描述】:

计算满足方程的第一个 n 的最快方法是什么

a^n mod m = 1

这里 a,n,m 可以是素数或合数 mod : 是模运算符

【问题讨论】:

  • 这个网站是用于编程问题,而不是数学作业。
  • 我需要使用代码来计算。我试图蛮力,但它在给定的时间限制内不起作用
  • 如果这是关于 CPU 时间的“最快”方法的问题,也许这个问题应该属于这里,但实际上,这似乎不太合适.
  • 这是一个编程问题的一部分
  • 是的,然后将“最佳”定义为性能最高或最快。

标签: c++ number-theory modular-arithmetic


【解决方案1】:

直接方式有什么问题:

int mod_order(int m, int a) {
    for(int n = 1, an = a; n != m; n++, an = an * a % m) if(an % m == 1) return n;
    return -1;
}

【讨论】:

  • 我试过蛮力。 2
  • @user1640967 是不是运行太慢了?如果有,m 有多大,蛮力需要多长时间,您预计需要多长时间?
  • 我想知道上述问题有没有更好的数学解决方案
  • 这与离散对数问题有关,已知该问题在 NP 中,但高度怀疑不在 P 中。有些算法确实可以提高性能,但它们仍然很慢(而不是取 O(m),他们取 O(sqrt(m)),这仍然很慢)
【解决方案2】:
  1. 如果 gcd(a,m)>1,则不存在这样的 n。 (很明显)
  2. 否则,如果 m 是素数,则 n=m-1。 (Proof)
  3. 否则(作为更一般的情况),n=ф(m),其中 ф 是欧拉的总函数。 (Proof)

如您所见,计算 ф(m) 本质上与 m 的因式分解相同。这可以在 sqrt(m) 时间或更短的时间内完成,具体取决于您使用的算法的复杂程度。简单的一个:

int phi(m){
  if(m==1) return 1;
  for(int d=2; d*d<m; ++d){
    if(m%d != 0) continue;
    int deg = 1; long acc=1;
    for(; m%(acc*d)==0; ++deg) acc*=d;
    acc /= d;
    return phi(m/acc)*acc*(d-1)/d;
  }
  return m-1;
}

更新:我的错。 a^(ф(m)) = 1 (mod m),但可以有较小的 n 值(对于 a=1,n=1,m 是什么没有区别;对于 a=14,m=15,n= 2)。 n 是 ф(m) 的除数,但有效地计算最小可能的 n 似乎很棘手。可以使用this 定理划分任务(对于各个余数,最小 n 是所有度数的最小公倍数)。但是当 m 是素数或有足够大的素数除数时,并且只有一个 a(而不是为许多具有相同 m 的不同 a 计算 n),我们就别无选择了。你可能想看看12

【讨论】:

    猜你喜欢
    • 2018-10-21
    • 1970-01-01
    • 2012-01-19
    • 1970-01-01
    • 1970-01-01
    • 2012-04-01
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多