数论计算中经常出现的一种运算就是求一个数的幂ab对另外一个数n个模的运算,即计算:ab mod n (a,b,n是正整数)
由于计算机只能表示有限位的整数,所以编程时模取幂的运算要注意值的大小范围,当ab的值超过整数范围时,mod运算便无法进行。
如何解决这个问题,我们引出一个能计算ab mod n的值的有用算法——反复平方法,首先我们必须明确:
d=ab mod n=(…((((a mod n)*a)mod n)*a)mod n…*a)mod n {共b个a}
下面采用分治法,例如,a^29次方=a^14^2*a,而a^14=(a^7)^2,a^7=(a^3)^2*a;a^3=a^2*a,一共只做了7次乘法,不知有没有发现,上述递归方式和二分查找方法很类似--每次规模近似减小一半,因此时间复杂度为O(logn),比O(n)好了很多。
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<ctime> #include<queue> #include<stack> #include<string> using namespace std; #define Max(a,b) a>b?a:b #define Min(a,b) a>b?b:a #define mem(a,b) memset(a,b,sizeof(a)) typedef long long LL; const int SIZE = 10000; const int MOD = 5767169; LL power_mod(LL a,LL b,LL mod) { LL ans=1; for(a%=MOD; b; b>>=1,a=a*a%MOD) { if(b&1) ans=ans*a%MOD; } return ans; }或者也可以这样写:
int PowerMod(int a, int b, int c) { int ans = 1; int k = a % c; while(b>0)//(k*k % c)2^b %c { if(b % 2 == 1)//如果是奇数 ans = (ans * k) % c; b = b/2; k = (k * k) % c;//k是不断代入,以代表每一次降一次幂 } return ans; }