luoguP5789 [TJOI2017]可乐(数据加强版) 矩阵乘法
比较简单的一道题.
矩阵乘法,唯一需要注意的地方就是这道题需要维护前缀和.
那么我们就多增加一个变量 $g$,表示前缀和,然后在设置矩阵的时候将 $g$ 要乘的一列中的元素都设置成前缀和即可.
做这种题的时候可以先打一个暴力来测试一下边界什么的,然后再去用矩阵乘法来优化.
code:
#include <cstdio> #include <algorithm> #include <cstring> #define N 103 #define mod 2017 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; int n,m,a[N][N]; struct M { int ma[N][N]; M(int x=0) { memset(ma,0,sizeof(ma)); for(int i=1;i<N;++i) ma[i][i]=x; } int *operator[](int x) { return ma[x]; } M operator*(const M b) const { M c; for(int i=1;i<N;++i) for(int j=1;j<N;++j) for(int k=1;k<N;++k) { (c.ma[i][j]+=ma[i][k]*b.ma[k][j]%mod)%=mod; } return c; } friend M operator^(M x,int y) { M tmp(1); while(y) { if(y&1) tmp=tmp*x; x=x*x; y>>=1; } return tmp; } }c0,X; int main() { // setIO("input"); scanf("%d%d",&n,&m); int x,y,z; for(int i=1;i<=n;++i) c0[i][i]=1; for(int i=1;i<=m;++i) { scanf("%d%d",&x,&y); c0[x][y]=c0[y][x]=1; } for(int i=1;i<=n;++i) { for(int j=1;j<=n;++j) c0[i][n+1]+=c0[i][j]; } c0[n+1][n+1]=1; X[1][1]=X[1][n+1]=1; int T; scanf("%d",&T); X=X*(c0^T); printf("%d\n",X[1][n+1]); return 0; }