快速幂运算
考虑求解一个数x的n次方:
线性方法:
long long f(int x,int n){
long ans=1;
while(n--){
ans=*x
}
return ans;
}
显然此算法的时间复杂度为o(n);所以当n很大的时候,此算法的效率就显得很低下
接下来考虑对于一种更高效的算法,以n=22来观察
此等式显然恒成立,接下来以n=22为例,在计算机中22的存储方式
很容易可以得到
回归到n上有
其中表示在二进制中对应的位数-1,表示在位上的取值(),于是有快速幂算法:
typedef long long ll;
ll mod_pow(ll x,ll n){
ll ans =1;
while(n>0){
if(n&1) res*=x;
x*=x;
n >>= 1
}
return ans;
}
Fibonacci数列
有如下数列:
用递归的方式:
int fib(int n){
if(n==1||n==2) return 1;
return fib(n-1)+fib(n-2);
}
过程如下:
显然有很多重复的计算,时间复杂度非常大,即使利用备忘录或者一个循环来解决,此时的复杂度仍,很多情况下依旧不能接受。
于是考虑快速矩阵幂:
于是可以构造如下矩阵
可能会有一点跳跃,但是联系矩阵乘法的本质,还是很好理解的!!!
记录这个矩阵为,于是有:
(倒退可知为0)
因此只要求 就可以求出,的计算参考上面的快速幂,此算法可在时间内求出第n项
//用二维vector表示矩阵
typedef vector<int> vec;
typedef vector<vec> mat;
const int M=1<<5;
//计算A*B
mat mul(mat&A,mat&B){
mat C(A.size(),vec(B[0].size()));
for(int i=0;i<A.size();i++){
for(int k=0;k<B.size();k++){
for(int j =0;j<B[0].size();j++){
c[i][j]=(c[i][j]+A[i][k]*B[k][j])%M;
}
}
}
return C;
}
//计算A^n
mat pow(mat A,ll n){
mat B(A.size(),vec(A.size()));
for(int i=0;i<A.size();i++){
B[i][i]=1;
}
while(n>0){
if(n&1) B=mul(B,A);
A=mul(A,A);
n>>=1;
}
return B;
}
//输入
ll n;
void solve(){
mat A(2,vec(2));
A[0][0]=1;A[0][1]=1;
A[1][0]=1;A[1][1]=0;
A=pow(A,n);
cout<<A[1][0];
}