我们知道如果用记忆化搜索逐项递推可以将复杂度降低到O(n),但是对于更大规模的输入,这个算法效率还是不够高,那么我们考虑更高效的算法:
二阶递推:f(n+2)=(1 1) f(n+1)
f(n+1) (1 0) f(n)
上面等式两边分别是矩阵,那么矩阵A就是等式右边第一个式子。
只要求出A的n次,就可以求出f(n)。我们使用快速幂来求,这个算法的复杂度为O(logn)
#include <iostream> #include <cstddef> #include <cstring> #include <vector> using namespace std; typedef long long ll; const int mod=10000; typedef vector<ll> vec; typedef vector<vec> mat; mat mul(mat &a,mat &b){ mat c(a.size(),vec(b[0].size())); for(int i=0;i<2;i++){ for(int j=0;j<2;j++){ for(int k=0;k<2;k++){ c[i][j]+=a[i][k]*b[k][j]; //c[i][j]%=mod; } } } return c; } mat pow(mat a,ll n){ mat res(a.size(),vec(a.size())); for(int i=0;i<a.size();i++) res[i][i]=1; while(n>0){ if(n&1){ res=mul(res,a); n-=1; } else{ a=mul(a,a); n/=2; } } return res; } ll solve(ll n){ 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); return a[1][0]; } int main(){ ll n; while(cin>>n){ cout<<solve(n)<<endl; } return 0; }