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;
}

浙公网安备 33010602011771号