1.快速幂适用问题: 大数据的a^b mod c
2.取模运算的一些公式:
(1)ab mod c = (a mod c)b mod c
(2)(a*b)mod c = [(a mod c)*(b mod c)]mod c
3.快速幂实现思路
(1)任何数字都可以表示成二进制的01串形式,同理:a^b mod c也可以把b拆成二进制串表示
b = b0*2^0 + b1 * 2^1 + b2*2^2 + b3* 2^3 + ....bx * 2^x +.....bn* 2^n
所以原式就等于: a^( b0*2^0 + b1 * 2^1 + b2*2^2 + b3* 2^3 + ....bx * 2^x +.....bn* 2^n) mod c;
等价于 : a^b0 * a^(b1*2) * a^(b2*4) * a^(b3*8) * ......* a^(bx*2^x) * ....* a^(bn * 2^n);
因为这里的b0....bn不是0就是一,一旦bx=0,则 a^(bx*2^x) =1, 这一项乘与不乘都是一样的,只有这一项的二进制数位置为1才乘进结果。
再进一步发现:如果b0....bn都是一,则 a a^2 a^4 a^8 a^16...... 每一项不管乘不乘,下一项都是成a = a*a的指数递增变化的。
(2)由上可得 :我们可以枚举b的二进制的每一位,若该位为0,则不乘入结果;若该位为1,则乘入结果;而要乘的是a^x, 不管乘不乘入结果,a都是指数递增的,a = a*a;( a a^2 a^4 a^8 a^16......)
(3) 如何枚举b的每一位二进制呢? 答案是用b>>=1;来往右移动b的二进制位;用b&1来判断b的最后一个二进制位是否为1,直到b==0结束。
4.实现代码:
#include <iostream> #include<bits/stdc++.h> using namespace std; long long int power(long long a,long long b,long long c) { a=a%c;//先一步取模把a制于c之下 long long int ans=1;//记录结果 while(b) { if(b&1)//如果b的二进制最右边一位为1 ans=(ans*a)%c;//计入结果 b>>=1;//b不断右移,枚举二进制位 a=(a*a)%c;//a不断指数递增(a a^2 a^4 a^8....) } return ans; } int main() { long long int a,b,c; while(cin>>a>>b>>c) { cout<<power(a,b,c)<<endl; } return 0; }
5.例题
(1)uva11609 Team
题意:问组合数,规律: n* 2^(n-1)
代码:
#include <iostream> //#include<bits/stdc++.h> using namespace std; long long int power(long long k) { long long int b=k-1; long long int a=2; long long int ans=1; while(b) { if(b&1) ans=(ans*a)%1000000007; b>>=1; a=(a*a)%1000000007; } return (ans*k)%1000000007; } int main() { int T; cin>>T; int t=0; long long int n; while(T--) { t++; cin>>n; cout<<"Case #"<<t<<": "<<power(n)<<endl; } return 0; }
(2)poj 1995
题意:求 (Ai^Bi +....+ An^Bn)mod M的值
代码:
#include <iostream> #include<cstdio> using namespace std; typedef long long ll; ll power(ll a,ll b,int c) { ll ans = 1; a%=c; while(b) { if(b&1) ans = (ans*a)%c; b>>=1; a = (a*a)%c; } return ans; } int main() { int z; scanf("%d",&z); while(z--){ int M,H; scanf("%d%d",&M,&H); ll sum = 0; for(int i=1;i<=H;i++){ ll a,b; scanf("%lld%lld",&a,&b); sum+=(power(a,b,M)%M); } printf("%lld\n",sum%M); } return 0; }