快速幂乘用的是二分的思想
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;
}
哎。。。不知道有什么好的方法来编辑公示,都是贴图的,挺麻烦的