0

What is fastest way to calculate the first n satisfying the equation

a^n mod m = 1

Here a,n,m can be prime or composite mod : is the modulus operator

rohangulati
  • 251
  • 1
  • 4
  • 12

2 Answers2

1

What is wrong with the direct way:

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;
}
SheetJS
  • 22,470
  • 12
  • 65
  • 75
  • I have tried brute force. 2 – rohangulati Oct 22 '13 at 19:01
  • @user1640967 is it running too slow? If so, how large is `m`, how long does the brute force take, and how long do you expect it to take? – SheetJS Oct 22 '13 at 19:02
  • I wanted to know is there any better mathematical solution to the above problem – rohangulati Oct 22 '13 at 19:07
  • This is related to the discrete logarithm problem, which is known to be in NP but highly suspected not to be in P. There are algorithms which do improve the performance, but they are still slow (instead of taking O(m), they take O(sqrt(m)) which is still pretty slow) – SheetJS Oct 22 '13 at 19:25
-1
  1. If gcd(a,m)>1, then there is no such n. (Obvious)
  2. Otherwise, if m is prime, n=m-1. (Proof)
  3. Otherwise (and as more general case), n=ф(m), where ф is Euler's totient function. (Proof)

As you can see, computing ф(m) is essentially the same as factorization of m. This can be done in sqrt(m) time or faster, depending on how convoluted is the algorithm you use. Simple one:

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

Upd: My bad. a^(ф(m)) = 1 (mod m), but there can be lesser value of n (for a=1, n=1, no difference what m is; for a=14, m=15, n=2). n is divisor of ф(m), but efficiently computing least possible n seems to be tricky. Task can be divided, by using this theorem (minimal n is least common multiple for all degrees for respective remainders). But when m is prime or has big enough prime divisor, and there is only one a (as opposed to computing n for many different a with the same m), we're kind of out of options. You may want to look at 1, 2.

Abstraction
  • 1,108
  • 11
  • 25