快速幂乘
来源:互联网 发布:淘宝直播海报图片 编辑:程序博客网 时间:2024/05/01 02:12
快速幂乘用的是二分的思想
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 __int64LL 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 7int 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 9973int 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 1000007long 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;}
哎。。。不知道有什么好的方法来编辑公示,都是贴图的,挺麻烦的
- 快速幂&快速乘
- zoj_2974_快速幂乘
- 快速幂乘
- 快速幂乘
- ACM-快速幂乘
- 【快速乘】【乘】【乘!!!!】
- 快速乘/快速幂/矩阵快速幂
- 快速乘 快速幂 矩阵快速幂
- 【bzoj2875】随机数生成器(矩乘快速幂+快速乘)
- 快速矩阵幂乘算法
- 快速幂乘 Java实现
- 快速幂和慢速乘
- zhx's contest----快速幂+快速乘
- 非递归快速幂快速乘
- 快速乘 + 快速幂 + 取模
- 【模板】(新)快速幂+快速乘
- 快速乘
- 二分幂,快速幂,矩阵快速幂,快速乘
- STM32中USART的使用方法
- 判断两个Integer是否相等不能用==,要用compareTo方法
- [Android]如何导入已有的外部数据库
- Sqlite入门与C/C++的应用
- 动态创建无级子菜单:乾坤大挪移无极紫菜汤
- 快速幂乘
- android导入外部已存在的数据库大于1M的数据库文件方法
- MySQL Cluster (三) --- 3台机器搭建集群环境
- lucene3.6中FSDirectory以及RAMDirectory的使用方法
- 应该记住的8位java人物
- Ubuntu笔记
- android raw读取超过1M文件的方法
- 黑马程序员_关于枚举
- chkdsk /f 修复优盘