洛谷P3873 [TJOI2010]天氣預報
阿新 • • 發佈:2020-12-07
題目
https://www.luogu.com.cn/problem/P3873
思路
線性遞推,自然就是矩乘辣(話說省選竟然有這種裸題嗎?)。
給個圖意思一下吧(以n=5為例):
\[\left[ \begin{matrix} w_1 & w_2 & w_3 & w_4 & w_5\end{matrix} \right]*\left[ \begin{matrix} 0 & 0 & 0 & 0 & a_5\\1 & 0 & 0 & 0 & a_4\\0 & 1 & 0 & 0 & a_3\\0 & 0 & 1 & 0 & a_2\\ 0 & 0 & 0 & 1 &a_1\end{matrix}\right]= \left[ \begin{matrix} w_2 & w_3 & w_4 & w_5 & w_6\end{matrix} \right] \]那麼要求第\(m\)項,把這個操作做\(m-n\)遍就可以了,此時答案矩陣的第1行第\(n\)列元素就是所求的\(w_m\)。
眾所周知矩乘滿足結合律,所以我們把中間的\(n*n\)矩陣拎出來,做個矩陣快速冪,再右乘上原來的\(w\)向量,就可以求出答案矩陣。
程式碼
#include<cstdlib> #define maxn 110 #define mod 4147 using namespace std; int w[maxn],a[maxn],n,m; struct matrix{ int d[101][101]; public: void init(){ int i,j; for(i=1;i<=n;++i) for(j=1;j<=n;++j) d[i][j]=0; } matrix operator *(matrix x){ int i,j,k; matrix ans; ans.init(); for(i=1;i<=n;++i) for(j=1;j<=n;++j) for(k=1;k<=n;++k) ans.d[i][j]=(ans.d[i][j]+d[i][k]*x.d[k][j])%mod; return ans; } } e; matrix pow(matrix x,int p){ matrix ans,base; ans=e;base=x; while(p){ if(p&1) ans=ans*base; base=base*base; p>>=1; } return ans; } int main(){ int i,j,ans; matrix f,x; scanf("%d%d",&n,&m); for(i=n;i>=1;i--) scanf("%d",&w[i]); for(i=1;i<=n;i++) scanf("%d",&a[i]); x.init();f.init();e.init(); for(i=1;i<=n;i++) e.d[i][i]=1; for(i=1;i<=n;i++) x.d[1][i]=w[i]; for(i=1;i<n;i++) f.d[i+1][i]=1; for(i=1;i<=n;i++) f.d[i][n]=a[n+1-i]; ans=(x*pow(f,m-n)).d[1][n]; printf("%d",ans); // system("pause"); return 0; }