快速幂算法
可迅速求出x^n。其主要理论依据如下:
1,当n为偶数时,x^n可以转为x^2的n/2次方。
2,当n为奇数时,x^n可以转为x^2的n/2次方,再乘以n。
typedef long long ll;
ll mod=maxn;
ll mod_pow(ll x,ll n)
{
ll res=1;
while(n>0)
{
if(n&1)//判断n的最低位是否为1,即是否是奇数
res=(res*x)%mod;
n>>=1;
x=(x*x)%mod;
}
return res;
}
先把n转化成二进制表示,然后每一位开始依次计算。如果二进制最低位为1,那么就将结果乘上x2^i ( i 的值取决于现在算到哪一位,如果是第0位则 i = 0)。每次将x平方,然后将n右移一位,继续下一位的计算。比如计算x22,就先把22转化成10110,最低位是0,res不变,x变成x2,右移变成1011;最低位是1,res乘上x2,x2再变为x4(也就是x2^2),右移变成101;最低位是1,res乘上x4,x4再变为x8,右移变成10……依次类推,最终结果也就是res = x2 * x4 * x16(此处没有考虑取余)。
快速乘法模版
typedef long long ll;
ll mod_mul(ll a,ll b,ll mod)
{
int res=0;
while(b)
{
if(b&1)
res=(res+a)%mod;
a=(a+a)%mod;
b>>=1;
}
return res;
}
矩阵快速幂
从原理上来讲矩阵快速幂和矩阵乘法是一样的,有人习惯写成结构体、类之类的封装好,我个人比较喜欢直接写函数。
const int N=3;//N是矩阵的行列值
void juzhen_mul(int a[][N],int b[][N],int n)//矩阵乘法
{
int tmp[N][N];
memset(tmp,0,sizeof(tmp));
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
for(int k=0;k<n;k++)
{
tmp[i][j]+=b[i][k]*b[j][k];
}
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
a[i][j]=tmp[i][j];
}
}
void mod_juzhen(int a[][N],int n)//矩阵快速幂
{
int res[N][N];
memset(res,0,sizeof(res));
for(int i=0;i<n;i++)//把矩阵初始化为1,和快速幂一样的
res[i][i]=1;
while(n)
{
if(n&1)
juzhen_mul(res,a,N);
juzhen_mul(a,a,N);
n>>=1;
}
}