快速幂
快速幂是在进行底数相同的乘法运算而幂数又极大的情况下使用的一种算法。
将幂次做二进制拆分,然后从低位到高位维护幂次积,同时若该位为 1
乘入答案。
模板
P1226
【模板】快速幂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #include<iostream> #include<cstdio> #define int unsigned long long using namespace std; int a,b,q; int qsm(int a,int b,int q) { int ans=1; while(b) { if(b&1)ans=(ans*a)%q; a=(a*a)%q; b>>=1; } return ans%q; } signed main() { cin>>a>>b>>q; cout<<a<<"^"<<b<<" mod "<<q<<"="<<qsm(a,b,q); return 0; }
|
矩阵快速幂
矩阵快速幂是指用矩阵乘法来求幂次方,矩阵乘法的结合律和交换律保证了运算的顺序。可以套用以上的快速幂。
经典例题是求斐波那契数列第 \(n\)
项(mod q)的值。和快速幂一样,这类题指数非常的大。
模板
P3390
【模板】矩阵快速幂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| #include<iostream> #include<cstdio> #include<algorithm> #include<cctype> #include<cstring> #include<cmath> using namespace std; inline long long read(){ long long x=0;bool w=0;char c=getchar(); while(!isdigit(c))w|=c=='-',c=getchar(); while(isdigit(c))x=x*10+(c^48),c=getchar(); return w?-x:x; } namespace star { const int maxn=105,mod=1e9+7; struct mat{ int n,a[maxn][maxn]; mat(){} mat(const int &x){n=x;memset(a,0,sizeof a);} inline void set(){for(int i=1;i<=n;i++) a[i][i]=1;} inline int* operator [] (const int &x) {return a[x];} inline const int* operator [] (const int &x) const {return a[x];} inline mat operator * (const mat &b) const{ mat ans(n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int k=1;k<=n;k++) ans[i][j]=(ans[i][j]+1ll*a[i][k]*b[k][j]%mod)%mod; return ans; } }now; inline mat fpow(mat a,long long b){ mat ans(a.n); ans.set(); for(;b;b>>=1,a=a*a)if(b&1)ans=ans*a; return ans; } int n; long long k; inline void work(){ n=now.n=read();k=read(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) now[i][j]=read(); now=fpow(now,k); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) printf("%d ",now[i][j]); puts(""); } } } signed main(){ star::work(); return 0; }
|
至于矩阵乘法还能干什么,应该应用也挺多的,但是我还没那个水平……
大家一起进步吧XD
UPD:NOI2020出来了,发现D1T1用到了矩阵快速幂,于是来更新我写的水的一p的第一篇博客。
也就是更新一个例子:矩阵快速幂优化DP
我们先来个简单版的DP:给你一个图(的邻接矩阵),边权全为1,求给定时间从s到t的路径方案数。
记f[i]表示i时状态,f[i]=f[i-1]*g。
所以我们要求x直接矩阵快速幂乘g的幂次就行了。
2022.9.29
UPD:高中时不求甚解写的东西……也不是我不想了解,是竞赛要求我在理解之前就使用矩阵。突然感觉竞赛和文化课其实没有什么本质区别。
没时间大改,把错误的地方尽量删了。