1.乘方取模问题:
给定正整数x,n,m,计算x^n(mod m)。
最简单代码,复杂度为O(n):
ll res=1;
for(int i=0;i<n;i++)
{
res=res*x%m;
}
2、快速幂,将n表示为2的幂次的和:,可以将x^n转化为:,依次由n的二进制位求x^2ki即可,复杂度降为O(logn)。例如,x^23=x^16*x^4*x^2*x(23二进制数是10111)。
typedef long long ll;
ll mod_pow(ll x,ll n,ll mod)
{
ll res=1;
while(n>0)
{
if(n&1) res=(res*x)%mod;
x=x*x%mod;//底数不断平方
n>>=1;
}
return res;
}
x为偶数时 x^n=(x^2)^n/2;x为奇数时,x^n=(x^2)^n/2*x,不断递归转为n/2情况,可以在O(logn)时间内完成幂运算:
ll mod_pow(ll x,ll n,int mod)
{
if(n==0) return 1;
ll res=mod_pow(x*x%mod,n/2,mod);
if(n&1) res=res*x%mod;
return res;
}
3.矩阵快速幂
将上面整数的快速幂中乘法换成矩阵乘法即可。
typedef long long ll;
struct matrix{
ll v[5][5];
matrix(){memset(v,0,sizeof(v));}
};
//矩阵乘法
matrix matrix_multi(matrix x,matrix y,ll mod)
{
matrix res;
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
if(x.v[i][j])//优化
for(int k=1;k<=N;k++)
{
res.v[i][k]+=x.v[i][j]*y.v[j][k];
res.v[i][k]%=mod;
}
return res;
}
//快速幂
matrix matrix_pow(matrix x,ll n,ll mod)
{
matrix res;
//初始化为单位矩阵
for(int i=1;i<=N;i++)
res.v[i][i]=1;
while(n>0)
{
if(n&1) res=matrix_multi(res,x,mod);
x=matrix_multi(x,x,mod);
n>>=1;
}
return res;
}