# (矩陣)快速冪 快速冪 --- * 把次方拆成一半,如果是奇數的話先拿掉一個次方 * ex: $2^{18}$可以拆成兩個$2^9$,因為$2^9$是奇數所以拆成$2^8\times2^1$,再把$2^8$拆為兩個$2^4$。以此類推到$2^1$。 * 複雜度$O(log(n))$ 程式碼: 遞迴: ```cpp= long long fastpow(long long a, long long b) { if (b == 0) return 1; long long res = fastpow(a, b / 2); if (b % 2) return res * res * a; else return res * res; } ``` iteration: ```cpp= long long fastpow(long long a, long long b) { long long res = 1; while (b > 0) { if (b & 1) res = res * a; a = a * a; b >>= 1; } return res; } ``` 矩陣快速冪 --- * 證明:https://math.stackexchange.com/questions/784710/how-to-prove-fibonacci-sequence-with-matrices/784723#784723 $A^{n+1}=\begin{pmatrix}F_{n+2} & F_{n+1} \\ F_{n+1} & F_{n} \end{pmatrix}$ * $fib(n)=A^{n-1}[0][0]$ * 用快速冪方法 matrix: ```cpp= struct mat{ long long a[2][2]={0}; mat operator * (mat &inp){ mat res; for(int i=0;i<2;++i) for(int j=0;j<2;++j) for(int k=0;k<2;++k) res.a[i][j]+=a[i][k]*inp.a[k][j]; return res; } }; ``` 快速冪: ```cpp= mat base; mat fpow(long long b){ if(b==1) return base; mat res=fpow(b/2); if(b & 1) return res*res*base; else return res*res; } ``` 主程式: ```cpp= int main(){ ios_base::sync_with_stdio(false); cin.tie(0); base.a[0][0]=1; base.a[0][1]=1; base.a[1][0]=1; long long n; cin>>n; if(n==0) cout << 0 << NL; else if(n==1) cout << 1 << NL; else cout << fpow(n-1).a[0][0] << NL; } ``` 大小矩陣通用模板: ```cpp= struct mat{ vector<vector<LL>> a; int wdt, len; // initilize size of matrix mat(int x, int y){ a.resize(x, vector<LL>(y,0)); len=x; wdt=y; } mat operator*(mat &inp){ mat res(len, inp.wdt); for(int i=0;i<len;++i) for(int j=0;j<inp.wdt;++j) for(int k=0;k<wdt;++k) res.a[i][j]+=a[i][k]*inp.a[k][j]; return res; } }; ```