背景:
上周为了那个勤写标兵
Lv3
\text{Lv3}
Lv3没有写博客,现在补补坑。
现在也没有拿到,差评。
题目传送门:
https://www.luogu.org/problemnew/show/P3758
题意:
一个无向图,现在在每一个点有
3
3
3种选择,走到相邻的格子或静止或自爆(从此不再工作),问
t
t
t时刻后的方案数。
思路:
思路与[TJOI2019]甲苯先生的字符串类似。
走到相邻的格子相当于两个点的初始矩阵的格子对应的为
1
1
1;
静止相当于对角线的格子为
1
1
1;
自爆相当于连向一个不存在的点,并且从此静止(即单向连向
0
0
0,并且
0
0
0也连向
0
0
0)。
自乘
t
t
t遍即可。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 2017
using namespace std;
int n,m,t;
int bz[35][35];
struct node
{
int a[35][35];
void clear()
{
memset(a,0,sizeof(a));
}
friend node operator * (const node &a,const node &b)
{
node c;
c.clear();
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
for(int k=0;k<=n;k++)
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j]%mod)%mod;
return c;
}
} base;
int work(int x)
{
node ans;
ans.clear();
for(int i=0;i<=n;i++)
ans.a[i][i]=1;
while(x)
{
if(x&1) ans=ans*base;
base=base*base;
x>>=1;
}
int sum=0;
for(int i=0;i<=n;i++)
sum=(sum+ans.a[1][i])%mod;
return sum;
}
int main()
{
int x,y;
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d %d",&x,&y);
bz[x][y]=bz[y][x]=1;
}
for(int i=0;i<=n;i++)
bz[i][0]=bz[i][i]=1;
memcpy(base.a,bz,sizeof(base.a));
scanf("%d",&t);
printf("%d",work(t));
}