关于快速幂这个算法,已经不想多说,很早也就会了这个算法,但是原来一直靠着模板云里雾里的,最近重新学习,发现忽视了一个重要的问题,就是若取模的数大于int型,即若为__int64的时候应该怎么办,这样就得用到乘法快速幂+乘方快速幂了。
快速幂一般是为了解决乘方取模问题的,显然思想就是二分,下面贴上快速幂模板:
1 __int64 mulpow(__int64 a,__int64 p,__int64 m) 2 { 3 __int64 ans = 1; 4 while(p) 5 { 6 if(p&1) 7 ans = ans * a % m; 8 p >>= 1; 9 a = a * a % m; 10 } 11 return ans; 12 }
但是以上代码有个问题,并不适合m超过int的情况,下面提供m超过int情况的解法
1 __int64 multi(__int64 a,__int64 b,__int64 n) //乘法快速幂 2 { 3 __int64 temp=0; 4 while(b) 5 { 6 if(b&1) 7 { 8 temp+=a; 9 if(temp>=n) temp-=n; 10 } 11 a<<=1; 12 if(a>=n) a-=n; 13 b>>=1; 14 } 15 return temp; 16 } 17 18 __int64 mulpow(__int64 a,__int64 m,__int64 n) //乘方快速幂 19 { 20 __int64 temp=1; 21 a%=n; 22 while(m) 23 { 24 if(m&1) temp=multi(temp,a,n); 25 a=multi(a,a,n); 26 m>>=1; 27 } 28 return temp; 29 }
但缺点就是速度慢了点,logn*logn的,感谢南理工的《ACM算法训练教程》
poj3761
链接:http://poj.org/problem?id=3761
排列组合题目,但是真不好想,看了别人的题解才做出来的,orz别人的思维,是自己太弱了
题解:http://blog.csdn.net/cscj2010/article/details/7820906
这题典型的用快速乘方幂+快速乘法幂会TLE的
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 #include<vector> 7 #include<algorithm> 8 using namespace std; 9 const int maxn=1000001; 10 __int64 a[maxn]; 11 const int mod=20100713; 12 __int64 mulpow(__int64 a,__int64 n,__int64 m) 13 { 14 __int64 temp=1; 15 while(n) 16 { 17 if(n&1) temp=temp*a%m; 18 a=a*a%m; 19 n>>=1; 20 } 21 return temp; 22 } 23 int main() 24 { 25 __int64 n,k,T; 26 a[0]=1; 27 for(int i=1;i<=maxn;i++) 28 a[i]=a[i-1]*i%mod; 29 scanf("%I64d",&T); 30 while(T--) 31 { 32 scanf("%I64d%I64d",&n,&k); 33 printf("%I64d ",(a[k]*((mulpow(k+1,n-k,mod))-mulpow(k,n-k,mod)+mod)%mod)%mod); 34 } 35 return 0; 36 }