一.乘法快速取余
算a*b%n
//乘法快速幂a*b%n,不写连乘是防止相乘时溢出 __int64 multi(__int64 a,__int64 b,__int64 n) { __int64 temp = 0; while(b!=0) { if(b%2==1) { temp+=a; if(temp>=n) temp-=n; } a*=2; if(a>=n) a-=n; b/=2; } return temp; }
二.乘方取模
算a^n%m
定理:要计算只包含加减乘的整数表达式除以整数m的余数时,可以在每步计算时对m取余
容易想到的代码如下:
int ans = 1;
for(int i=1;i<=n;i++)
ans=ans*a%m;
这样做时间发杂度为O(n),如果n=10^9,那么肯定会超时;
优化后的代码:
1 __int64 mutimod(__int64 a,__int64 n,__int64 m) 2 { 3 __int64 ans=1; 4 while(n) 5 { 6 if(n&1LL)//判断是否为奇数 7 ans=ans*a%m; 8 n>>=1LL; 9 a=a*a%m; 10 } 11 return ans; 12 }
//乘方快速幂a^n%m __int64 multimod(__int64 a,__int64 n,__int64 m) { __int64 ans=1; while(n!=0) { if(n%2==1) ans=multi(ans,a,m); a=multi(a,a,m); n/=2; } return ans; }
三.矩阵快速幂
A是一个矩阵,求A^n;
代码如下:
#include <iostream> #include<cstdio> #include<cstring> using namespace std; const int mod = 10000; const int N = 2;//矩阵的维数,角标从0开始 struct Matrix { __int64 v[N][N]; Matrix() { memset(v,0,sizeof(v)); } }; //矩阵的乘法p1*p2 Matrix multi(Matrix p1,Matrix p2) { Matrix res; for(int i=0;i<N;i++) for(int j=0;j<N;j++) if(p1.v[i][j])//代码优化,是0的话就不用计算 for(int k=0;k<N;k++) //根据具体需要修改mod res.v[i][k]=(res.v[i][k]+(p1.v[i][j]*p2.v[j][k]))%mod; return res; } //矩阵的快速幂p^k Matrix pow(Matrix p,__int64 k) { Matrix t; for(int i=0;i<N;i++)//初始化为单位矩阵 t.v[i][i]=1; while(k) { if(k&1) t=multi(t,p); p=multi(p,p); k=k>>1; } return t; }