洛谷P1397 [NOI2013]矩陣遊戲
阿新 • • 發佈:2020-12-06
題意簡述
給定一個二維的遞推方程,已知第一項\((1,1)\)求其第\((n,m)\)項
分析
一道矩陣乘法基礎題
一看到遞推式還沒有特殊條件就知道是矩陣快速冪
但是這個\(n,m\)的範圍著實是不正常
所以考慮到要用個某某定理或者性質把\(n,m\)的範圍縮小
這裡就是費馬小定理了
容易發現,這裡的矩陣乘法是滿足費馬小定理的,但是當\(a=1\)的情況要特判,(至於為什麼詳見這篇部落格或者這篇部落格)
所以接下來我們可以開始構造狀態矩陣
構造狀態轉移矩陣的方法:若狀態矩陣中第 \(x\) 個數對下一單位時間狀態矩陣中第 \(y\) 個數有影響,則把轉移矩陣的第 \(x\)行第 \(y\)
我們發現,狀態矩陣中第一個數要乘\(a\)加\(b\),那麼根據上面的定義很容易想到,狀態轉移矩陣的第一列分別就是 \(a\),\(b\),分別對應\(f_{(i-1,j)}\)和 \(1\)。我們會發現狀態矩陣中第二個值是不變的,它賦值為 \(1\) 的意義在於能夠剛好計算最後的 \(+b\)。
所以我們可以把單獨一行的轉移方程寫出來:
\(\left\{ \begin{matrix} a & 0\\ b & 1 \end{matrix} \right\}\)
那麼其實我們每一行轉移過後就是行與行之間的轉移,那麼我們可以把這個轉移方程也直接寫出來:
\(\left\{ \begin{matrix} c & 0\\ d & 1 \end{matrix} \right\}\)
(其實一點變化都沒有)
所以我們手摸一下,可以直接得出:
我們的初始狀態的矩陣要乘上
\[\left[ \begin{matrix} a & 0\\ b & 1 \end{matrix} \right]^{(m-1)*n} * \left[ \begin{matrix} c & 0\\ d & 1 \end{matrix} \right]^{(n-1)} \]最後答案就是初始矩陣的元素\(f_{(1,1)}\)
那麼這道題就結束了
程式碼
程式碼附上
#include<bits/stdc++.h> using namespace std; template <typename T> inline void read(T &x){ x=0;char ch=getchar();bool f=false; while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} x=f?-x:x; return ; } template <typename T> inline void write(T x){ if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10^48); return ; } #define ll long long const ll MOD=1e9+7,N=1e6+5; #define inc(a,b) (a+b>=MOD?a+b-MOD:a+b) struct Matrix{ ll a[3][3]; Matrix(){memset(a,0,sizeof(a));} Matrix operator * (Matrix B){ Matrix C; for(int i=1;i<3;i++){ for(int j=1;j<3;j++){ for(int k=1;k<3;k++){ C.a[i][j]=inc(C.a[i][j],a[i][k]*B.a[k][j]%MOD); } } } return C; } }; Matrix QuickPow(Matrix A,ll y){ Matrix res; res.a[1][1]=res.a[2][2]=1; while(y){ if(y&1) res=res*A; A=A*A; y>>=1; } return res; } Matrix ans,base,base1; string nn,mm; ll a,b,c,d,n,m; int main(){ cin>>nn>>mm>>a>>b>>c>>d; int len1,len2; len1=nn.size(),len2=mm.size(); for(int i=0;i<len1;i++) n=(n*10+nn[i]-'0')%(a==1?MOD:MOD-1); for(int i=0;i<len2;i++) m=(m*10+mm[i]-'0')%(a==1?MOD:MOD-1); ans.a[1][1]=1,ans.a[1][2]=1; base.a[1][1]=a,base.a[2][1]=b,base.a[2][2]=1; base=QuickPow(base,m-1); base1.a[1][1]=c,base1.a[2][1]=d,base1.a[2][2]=1; base=base*base1; base=QuickPow(base,n-1); base1.a[1][1]=a,base1.a[2][1]=b,base1.a[2][2]=1; base1=QuickPow(base1,m-1); write((ans*(base*base1)).a[1][1]); return 0; }