1.普通快速幂
快速幂模板:
int Quick_pow(int a,int b)
{
int ans=1;
while(b){
if(b&1)
ans=ans*a;
a=a*a;
b>>=1;
}
return ans;
}
矩阵快速幂模板
matrix Quick_pow(matrix a,long long k)
{
matrix ans;
ans.init();
while(k)
{
if(k&1) ans=mul(ans,a);
a=mul(a,a);
k>>=1;
}
return ans;
}
2.快速幂+求模
快速幂求模模板:
int Quick_pow(int a,int b,int c)//a-底数,b-指数,c-mod,
{
int ans=1;
a=a%c;//先将a化为a的mod的范围内
while(b){
if(b&1)
ans=(ans*a)%c;
a=(a*a)%c;//a的模乘以b的模的mo等于a乘积的模
b>>=1;//(a*b)%c=(a%c)*(b%c)%c
}
return ans;
}
POJ1995:Raising Modulo Numbers
板题快速幂求模地址
#include<cstdio>
int Quick_pow(int a,int b,int c)
{
int ans=1;
a=a%c;
while(b){
if(b&1)
ans=(ans*a)%c;
a=(a*a)%c;
b>>=1;
}
return ans;
}
int main()
{
int t,h,c;
scanf("%d",&t);
while(t--){
int sum=0,a,b;
scanf("%d",&c);
scanf("%d",&h);
for(int i=0;i<h;++i)
{
scanf("%d %d",&a,&b);
sum=(sum+Quick_pow(a,b,c))%c;
}
printf("%d\n",sum);
}
return 0;
}
3.矩阵快速幂
a.矩阵快速幂板题
POJ3070:Fibonacci
链接
#include<cstdio>
#include<cstring>
const int maxn=2;//阶数
//const int mod=1000000007;
const int mod=10000;
int n;
struct matrix{
int a[100][100];
void init()
{
memset(a,0,sizeof(a));
for(int i=0;i<maxn;++i) a[i][i]=1;
}
};
matrix mul(matrix x,matrix y)
{
matrix c;
memset(c.a,0,sizeof(c.a));
for(int i=0;i<maxn;++i){
for(int j=0;j<maxn;++j){
for(int k=0;k<maxn;++k){
c.a[i][j]+=x.a[i][k]*y.a[k][j];
c.a[i][j]%=mod;
// c.a[i][j]=c.a[i][j]%mod+x.a[i][k]*y.a[k][j]%mod;
}
}
}
return c;
}
matrix Quick_pow(matrix a,int k)
{
matrix ans;
ans.init();
while(k)
{
if(k&1) ans=mul(ans,a);
a=mul(a,a);
k>>=1;
}
return ans;
}
int main()
{
matrix a;
a.a[0][0]=1,a.a[0][1]=1,a.a[1][0]=1,a.a[1][1]=0;
while(~scanf("%d",&n)&&n!=-1)
{
matrix ans=Quick_pow(a,n);
printf("%d\n",ans.a[0][1]);
}
return 0;
}
b.板题的增强
斐波那契数列的前n项平方和:F[N]=F[N]*F[N+1]
牛客小白月赛20:
斐波那契数列前n项平方和
#include<cstdio>
#include<cstring>
const long long maxn=2;//阶数
const long long mod=1000000007;
struct matrix{
long long a[2][2];
void init()//结构体内的结构体成员数组的初始化函数
{
memset(a,0,sizeof(a));
for(int i=0;i<maxn;++i) a[i][i]=1;
}
};
matrix mul(matrix x,matrix y)
{
matrix c;
memset(c.a,0,sizeof(c.a));//结构体成员数组的清0
for(long long i=0;i<maxn;++i){//maxn为全局变量的阶数
for(long long j=0;j<maxn;++j){
for(long long k=0;k<maxn;++k){
// c.a[i][j]+=x.a[i][k]*y.a[k][j];
// c.a[i][j]%=mod;
c.a[i][j]=(c.a[i][j]+x.a[i][k]*y.a[k][j])%mod;//更高效的运算大数求模
}
}
}
return c;
}
matrix Quick_pow(matrix a,long long k)//结构体函数返回结构体
{
matrix ans;
ans.init();
while(k)//矩阵快速幂
{
if(k&1) ans=mul(ans,a);
a=mul(a,a);
k>>=1;
}
return ans;
}
int main()
{
long long n;
matrix a;
a.a[0][0]=1,a.a[0][1]=1,a.a[1][0]=1,a.a[1][1]=0;
scanf("%lld",&n);
matrix ans1=Quick_pow(a,n);
long long result1=ans1.a[0][1];//为什么取的是a[0][1]下面图片有讲解自行体会
matrix ans2=Quick_pow(a,n+1);
long long result2=ans2.a[0][1];
printf("%lld\n",result1*result2%mod);//乘积后可能再次大于模所以再一次求模
return 0;
}