快速幂乘
快速幂乘用的是二分的思想
a^b%c,当b比较大时可将其分解
当b为偶数时,a^b%c=(a^(b/2)*a^(b/2))%c;当b为奇数时,a^b%c=(a^(b/2)*a^(b/2)*a)%c
AOJ-569-乘的更快
http://icpc.ahu.edu.cn/OJ/Problem.aspx?id=569
赤裸裸的快速幂乘
#include<stdio.h> #include<string.h> #include<stdlib.h> #define Mod 99991 __int64 ans,x,y; void power(__int64 n) { if(n==0) { ans=1; return; } if(n==1) { ans=x%Mod; return; } power(n>>1); //二分 ans=((ans%Mod)*(ans%Mod))%Mod; if(n&1) //n为奇数时需要多乘一次 { ans=((ans%Mod)*(x%Mod))%Mod; return; } return; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%I64d %I64d",&x,&y); power(y); printf("%I64d\n",ans); } return 0; }
FZU-1752-A^B mod C
http://acm.fzu.edu.cn/problem.php?pid=1752
这题也是快速幂乘,要注意的是a比较大时,需要将b按二进制分解,否则会溢出
在刘汝佳的黑书上也有简单的介绍
#include<stdio.h> #include<string.h> #include<stdlib.h> #define LL __int64 LL mul(LL a,LL b,LL c) //计算a*b%c,将b按二进制分解 { LL res=0; for(;b;b>>=1) { if(b&1) //末位为1 { res+=a; while(res>=c) res-=c; } a<<=1; while(a>=c) a-=c; } return res; } LL qmod(LL a,LL b,LL c) //幂乘,将b分解为2进制 { LL res=1; for(;b;b>>=1) { if(b&1) res=mul(a,res,c); a=mul(a,a,c); } return res; } int main() { LL a,b,c; while(scanf("%I64d%I64d%I64d",&a,&b,&c)!=EOF) printf("%I64d\n",qmod(a%c,b,c)); return 0; }
快速幂乘也可以用于矩阵的乘法,还是二分的思想
f(n)=A*f(n-1)+B*f(n-2) (Mathtype中,按住Shift和Ctrl,再按空格键,即可添加空格)
用矩阵乘法递推求得递推可得,这样只需求
对于,当n为偶数时,
n为奇数时,
HDU-1005-Number Sequence
http://acm.hdu.edu.cn/showproblem.php?pid=1005
这题可用矩阵快速幂乘
#include<stdio.h> #include<string.h> #include<stdlib.h> #define Mod 7 int a,b,n; int matrix[2][2]; int temp[2][2]; void power(int x) { int i,j,k; if(x==0) { matrix[0][0]=matrix[1][1]=1; matrix[0][1]=matrix[1][0]=0; return; } if(x==1) { matrix[0][0]=a%Mod; matrix[0][1]=b%Mod; matrix[1][0]=1; matrix[1][1]=0; return; } power(x>>1); //二分 for(i=0;i<=1;i++) //矩阵乘法 for(j=0;j<=1;j++) { temp[i][j]=0; for(k=0;k<=1;k++) temp[i][j]+=(matrix[i][k]*matrix[k][j])%Mod; } if(x&1) //x为奇数 { matrix[0][0]=(temp[0][0]*a+temp[0][1])%Mod; matrix[0][1]=(temp[0][0]*b)%Mod; matrix[1][0]=(temp[1][0]*a+temp[1][1])%Mod; matrix[1][1]=(temp[1][0]*b)%Mod; return; } for(i=0;i<=1;i++) for(j=0;j<=1;j++) matrix[i][j]=temp[i][j]%Mod; return; } int main() { while(scanf("%d %d %d",&a,&b,&n),a||b||n) { if(n==1||n==2) { printf("1\n"); continue; } power(n-2); printf("%d\n",(matrix[0][0]*1+matrix[0][1]*1)%Mod); } return 0; }
HDU-1579-Tr A
http://acm.hdu.edu.cn/showproblem.php?pid=1575
这题是求矩阵高次幂的对角线之和,也可用矩阵快速幂乘
#include<stdio.h> #include<string.h> #include<stdlib.h> #define Mod 9973 int temp[15][15]; int matrix[15][15]; int a[15][15]; int n; void power(__int64 x) { int i,j,k; if(x==1) { for(i=0;i<n;i++) for(j=0;j<n;j++) matrix[i][j]=a[i][j]; return; } power(x>>1); for(i=0;i<n;i++) for(j=0;j<n;j++) { temp[i][j]=0; for(k=0;k<n;k++) temp[i][j]+=((matrix[i][k]*matrix[k][j])%Mod); temp[i][j]%=Mod; //防止溢出,不加会WA } if(x&1) { for(i=0;i<n;i++) for(j=0;j<n;j++) { matrix[i][j]=0; for(k=0;k<n;k++) matrix[i][j]+=(temp[i][k]*a[k][j])%Mod; matrix[i][j]%=Mod; } return; } for(i=0;i<n;i++) for(j=0;j<n;j++) matrix[i][j]=temp[i][j]; return; } int main() { int i,j,t,sum; __int64 k; scanf("%d",&t); while(t--) { scanf("%d %I64d",&n,&k); for(i=0;i<n;i++) for(j=0;j<n;j++) { scanf("%d",&a[i][j]); a[i][j]%=Mod; } power(k); sum=0; for(i=0;i<n;i++) sum+=(matrix[i][i]%Mod); printf("%d\n",sum%Mod); } return 0; }
NYOJ-301-递推求值
http://acm.nyist.net/JudgeOnline/problem.php?pid=301
这题也用矩阵幂乘来递推求值,和上题的区别是多了个常数
f(x)=a*f(x-2)+b*f(x-1)+c
构造一个矩阵即可
#include<stdio.h> #include<string.h> #include<stdlib.h> #define Mod 1000007 long long a,b,c,f1,f2,n; long long p[3][3]; long long temp[3][3]; long long matrix[3][3]; void init() { p[0][0]=0; p[0][1]=a; p[0][2]=0; p[1][0]=1; p[1][1]=b; p[1][2]=0; p[2][0]=0; p[2][1]=1; p[2][2]=1; } void power(long long m) { int i,j,k; if(m==0) { memset(matrix,0,sizeof(matrix)); matrix[0][0]=matrix[1][1]=matrix[2][2]=1; return; } if(m==1) { for(i=0;i<=2;i++) for(j=0;j<=2;j++) matrix[i][j]=p[i][j]; return; } power(m>>1); for(i=0;i<=2;i++) for(j=0;j<=2;j++) { temp[i][j]=0; for(k=0;k<=2;k++) temp[i][j]+=(matrix[i][k]*matrix[k][j])%Mod; } if(m&1) { for(i=0;i<=2;i++) for(j=0;j<=2;j++) { matrix[i][j]=0; for(k=0;k<=2;k++) matrix[i][j]+=(temp[i][k]*p[k][j])%Mod; } return; } for(i=0;i<=2;i++) for(j=0;j<=2;j++) matrix[i][j]=temp[i][j]; return; } int main() { int t; long long ans; scanf("%d",&t); while(t--) { scanf("%lld %lld %lld %lld %lld %lld",&f1,&f2,&a,&b,&c,&n); if(a<0) a+=Mod; if(b<0) b+=Mod; if(c<0) c+=Mod; if(n==1) { printf("%lld\n",f1); continue; } if(n==2) { printf("%lld\n",f2); continue; } init(); power(n-2); ans=((matrix[0][1]*f1)%Mod+(matrix[1][1]*f2)%Mod+(matrix[2][1]*c)%Mod)%Mod; printf("%lld\n",ans); } return 0; }
哎。。。不知道有什么好的方法来编辑公示,都是贴图的,挺麻烦的
posted on 2012-06-29 21:59 java课程设计例子 阅读(283) 评论(0) 编辑 收藏 举报