第一篇博文,讲一点简单的内容吧。
快速幂在很多比赛中都是非常常见的题目。当然,我们必须在很短的时间内解决这样的“代码”
下面我们就来考虑一下快速幂基于什么样的原理?
1、二分法
对于任意的 x * y 都有 x % n * y % n (注意 xk != xk % n)
所以 xk = xk / 2 * xk / 2 % n(k % 2 == 0 若 k % 2 == 1 就 多乘上一个 x 即可)
所以 我们不难想出如下的代码
1 #include<cstdlib> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 int a,b,c; 6 int fast_mod(int a,int b,int c) 7 { 8 if(b == 0) return 1; 9 int t = fast_mod(a,b/2,c); 10 if(b % 2) 11 return t * t % c * a % c; 12 else 13 return t * t % c; 14 } 15 int main() 16 { 17 scanf("%d %d %d",&a,&b,&c); // a ^ b % c 18 printf("%d",fast_mod(a,b,c)); 19 return 0; 20 }
2、倍增法
倍增法是基于位运算的一种快速幂的求法,一般利用迭代实现,常数比二分更优。其算法原理如下:
我们知道a^(p+q) = a^p*a^q;
所以,我们可以提前算出a^(2^i)(下面程序中how数组)的值,每次通过位运算来得出结果,最后相乘。
举个例子把:8 ^ 5 mod 9,5 = 101(2);
所以,左边 = (8 ^ 1 mod 9)*(8 ^ (1<<2) mod 9)
代码如下:
1 #include<cstdio> 2 #include<cstdlib> 3 using namespace std; 4 long long a,b,c; 5 long long how[64]; //倍增数组 6 7 void deal() //预处理出倍增数组:how[i] = a^(2^i)%c 8 { 9 int i = 0; 10 how[i] = a%c; 11 for (i = 1;i<64;i++) 12 how[i] = how[i-1]*how[i-1]%c; 13 } 14 15 long long quick(long long a,long long b,long long c) 16 { 17 int i = 0,ret = 1; 18 while (b) 19 { 20 if (b & 1) 21 ret = (ret*how[i])%c; 22 b >>= 1; 23 i++; 24 } 25 return ret; 26 } 27 28 int main() 29 { 30 freopen("test.in","r",stdin); 31 freopen("test.out","w",stdout); 32 scanf("%I64d %I64d %I64d",&a,&b,&c); 33 deal(); 34 printf("%I64d",quick(a,b,c)); 35 return 0; 36 }
原文:http://www.cnblogs.com/RHX-LMY/p/3986834.html