快速幂矩阵快速幂
快速冪
題目鏈接:https://www.luogu.org/problemnew/show/P1226
快速冪用了二分的思想,即將\(a^{b}\)的指數b不斷分解成二進制的形式,然后相乘累加起來,就是用\(a^{b/2}×a^{b/2}\)去求\(a{^b}\)。
例如:\(a^{11}=a^{(2^0+2^1+2^3)}\)
程序實現是這樣的(使用了位運算):
ll pow(ll b,ll p,ll k) {for(;p;p>>=1) // >> 右移等同于 /2{if(p&1) //判斷p是否為奇數,是則返回trueans=ans*b%k;b=b*b%k;}return ans%k; }AC代碼
#include<iostream> #include<cstdio> #define ll long long using namespace std; int k=1,m=0,flag; ll ans=1; ll pow(ll b,ll p,ll k) {for(;p;p>>=1){if(p&1)ans=ans*b%k;b=b*b%k;}return ans%k; } int main() {ll b,p,k;cin>>b>>p>>k;ll m=pow(b,p,k)%k;printf("%d^%d mod %d=%d",b,p,k,m); return 0; }矩陣快速冪
題目鏈接:https://www.luogu.org/problemnew/show/P3390
矩陣運算法則
矩陣A的大小為\(n×m\),B的大小為\(n×k\),設\(C=A×B\)
則\(C_{i,j}=\sum\limits_{k=1}^{n}A_{i,p}×B_{p,j}\)
例:
矩陣乘滿足結合律:\((AB)C=A(BC)\)
有一種特殊的矩陣:單位矩陣,它從左上角到右下角的對角線上的元素均為1,除此以外全都為0。它在矩陣乘中相當于數乘中的1,即任何矩陣乘它都等于本身。
以上這些就是打出矩陣快速冪前必備的基礎知識了。
代碼實現
- 理解了矩陣乘法之后,我們就可以用函數來模擬矩陣乘了。
- 因為矩陣乘滿足結合律,所以快速冪完全適用于矩陣,矩陣快速冪和普通快速冪幾乎一模一樣,不同點在于“*”號改成了Mul函數(不會普通快速冪的請前往P1226)
知道了這些后,這道題基本就可以AC了
最后要注意開long long,不然會爆零。
AC代碼:
#include<iostream> #include<cstring> #define mod 1000000007 #define ll long long using namespace std; struct Mat{ll m[101][101]; };//結構體存矩陣 Mat a,e;//a是輸入的矩陣,e是單位矩陣 ll n,p; Mat Mul(Mat x,Mat y) //矩陣乘 {Mat c;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)c.m[i][j]=0;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)for(int k=1;k<=n;k++){c.m[i][j]=c.m[i][j]%mod+x.m[i][k]*y.m[k][j]%mod;}return c; } Mat pow(Mat x,ll y) //矩陣快速冪 {Mat ans=e;while(y){if(y&1)ans=Mul(ans,x); x=Mul(x,x);y>>=1;}return ans; }int main() {//輸入 cin>>n>>p;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)cin>>a.m[i][j];//算法核心 for(int i=1;i<=n;i++)e.m[i][i]=1; Mat ans=pow(a,p);//輸出 for(int i=1;i<=n;i++){for(int j=1;j<=n;j++)cout<<ans.m[i][j]%mod<<" ";cout<<endl;} return 0; }廣告時間
在下的洛谷博客&&博客園博客
轉載于:https://www.cnblogs.com/wxl-Ezio/p/8520427.html
總結
- 上一篇: 不备案印章规格标准?
- 下一篇: linux和windows程序栈区别?