题解 P3758 【[TJOI2017]可乐】
首先邻接矩阵用来做矩阵乘法还是非常有意义的
如果一个邻接矩阵
这道题不一样的就是可以在与原地停留还有自爆
原地停留的话那就自己向自己连一条边,那就可以自己来回走了
自爆的话就设置一个虚点
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#define re register
#define maxn 35
const int mod=2017;
int ans[maxn][maxn],a[maxn][maxn];
int n,m,T;
inline int read()
{
char c=getchar();
int x=0;
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9')
x=(x<<3)+(x<<1)+c-48,c=getchar();
return x;
}
inline void did_a()
{
int mid[maxn][maxn];
for(re int i=1;i<=n+1;i++)
for(re int j=1;j<=n+1;j++)
mid[i][j]=a[i][j],a[i][j]=0;
for(re int i=1;i<=n+1;i++)
for(re int j=1;j<=n+1;j++)
for(re int p=1;p<=n+1;p++)
{
a[i][j]+=mid[i][p]*mid[p][j];
if(a[i][j]>mod) a[i][j]%=mod;
}
}
inline void did_ans()
{
int mid[maxn][maxn];
for(re int i=1;i<=n+1;i++)
for(re int j=1;j<=n+1;j++)
mid[i][j]=ans[i][j],ans[i][j]=0;
for(re int i=1;i<=n+1;i++)
for(re int j=1;j<=n+1;j++)
for(re int p=1;p<=n+1;p++)
{
ans[i][j]+=a[i][p]*mid[p][j];
if(ans[i][j]>mod) ans[i][j]%=mod;
}
}
inline void quick(int b)
{
while(b)
{
if(b&1) did_ans();
b>>=1;
did_a();
}
}
int main()
{
n=read(),m=read();
int x,y;
for(re int i=1;i<=m;i++)
x=read(),y=read(),a[x][y]=a[y][x]=1;
for(re int i=1;i<=n;i++)
a[i][i]=a[i][n+1]=1;
a[n+1][n+1]=1;
for(re int i=1;i<=n+1;i++)
ans[i][i]=1;
T=read();
quick(T);
int num=0;
for(re int i=1;i<=n+1;i++)
num=(num+ans[1][i])%mod;
std::cout<<num;
return 0;
}