2 ^ x mod n = 1问题

问题介绍:给一个整数n,找到最小的x(x > 0),使满足 2 ^ x mod n = 1

问题解析:对于a * b % c 有公式:    a * b % c = ((a % c) * (b % c)) % c.

    所以可以通过递归求解a ^ b mod c.穷举x,便可写出以下代码:

    

 1 #include<stdio.h>
 2 #include<iostream>
 3 using namespace std;
 4 
 5 //a ^ b % c
 6 int get_mod(__int64 a, int b, int c)
 7 {
 8     if(b == 1)
 9         return a % c;
10     return get_mod(a, b - 1, c) * a % c;
11     //((a ^ (b - 1) % c) * a) % c
12 }
13 
14 
15 int main()
16 {
17     int n;
18     while(cin>>n)
19     {
20         if(n % 2 == 0 || n <= 1)
21             printf("2^? mod %d = 1
", n);
22         else
23         {
24             int x;
25             for(x = 1; ; x++)
26                 if(get_mod(2, x, n) == 1)
27                 {
28                     printf("2^%d mod %d = 1
", x, n);
29                     break;
30                 }
31         }
32     }
33     return 0;
34 }
35  

显然,当n比较大时,上述算法的效率很低,最终导致超时...需要修改莫幂运算的算法.

   需要使用一种数学方法:蒙哥马利幂模运算(是快速计算a^b%k的一种算法).

     由于a * a % c =  ((a % c) * (a % c)) % c   =  ((a % c)^2) % c. 可以将两次运算转换为一次乘方运算.

     所以可以通过这样的递归公式:a ^ 2n % c = (a ^ n % c) ^ 2 % c.可以二分计算.

    效率由原来的n变为log2(n).当n很大时,效率提升数万倍.

    注意,当n为奇数时,需要利用正常的递推方法使n - 1为偶数带入下一次计算.

   修改后的代码:

   

 1 //给一个整数n,找到最小的x(x > 0),使满足 2 ^ x mod n = 1
 2 
 3 #include<stdio.h>
 4 #include<math.h>
 5 #include<iostream>
 6 using namespace std;
 7 
 8 //a ^ b % c
 9 int get_mod(__int64 a, int b, int c)
10 {
11     if(b == 1)
12         return a % c;
13     if(b % 2 == 1)
14         return (get_mod(a, b - 1, c) * (a % c)) % c;
15     return (int)pow(get_mod(a, b / 2, c), 2) % c; 
16     //((a ^ (b - 1) % c) * a) % c
17 }
18 
19 
20 int main()
21 {
22     int n;
23     while(cin>>n)
24     {
25         if(n % 2 == 0 || n <= 1)
26             printf("2^? mod %d = 1
", n);
27         else
28         {
29             int x;
30             for(x = 1; ; x++)
31                 if(get_mod(2, x, n) == 1)
32                 {
33                     printf("2^%d mod %d = 1
", x, n);
34                     break;
35                 }
36         }
37     }
38     return 0;
39 }
40  
原文地址:https://www.cnblogs.com/bmdx/p/3198256.html