[SDOI2009]HH去散步

题目要求对于同一条边,不能走过去后立刻走回来,所以很明显我们需要把一条边拆成两条来做。
此时我们的状态也需要改变:num[i][j][t]表示从第i条边到第j条边,经过时间为t的方案数。
因为我们的方案是设第i条边到第j条边,所以初始矩阵赋值时,其实已经过去了一个单位的时间。所以我们只需要,再累乘矩阵T-1次即可。
#include <bits/stdc++.h>
using namespace std;
const int N=130,MOD=45989;
int n,m,t,A,B,cnt,u,v,sum;
struct edge{int x,y;}e[N];
struct number{int num[N][N];}a,ans;

inline number mul(number a,number b)
{
	number c;
	for (register int i=2; i<=cnt; ++i)
	for (register int j=2; j<=cnt; ++j) c.num[i][j]=0;
	for (register int i=2; i<=cnt; ++i)
	for (register int j=2; j<=cnt; ++j)
	for (register int k=2; k<=cnt; ++k)
	c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j]%MOD)%MOD;
	return c; 
}

inline void pow(int k)
{
	while (k)
	{
		if (k&1) ans=mul(ans,a);
		a=mul(a,a);
		k>>=1;
	}
}

int main(){
	scanf("%d%d%d%d%d",&n,&m,&t,&A,&B);
	cnt=1;
	for (register int i=1; i<=m; ++i)
	{
		scanf("%d%d",&u,&v);
		e[++cnt].x=u; e[cnt].y=v;
		e[++cnt].x=v; e[cnt].y=u;
	}
	for (register int i=2; i<=cnt; ++i)
	for (register int j=2; j<=cnt; ++j) if (i!=(j^1) && e[i].y==e[j].x) a.num[i][j]=1;
	for (register int i=2; i<=cnt; ++i) ans.num[i][i]=1;
	
	pow(t-1);
	for (register int i=2; i<=cnt; ++i)
	for (register int j=2; j<=cnt; ++j) 
	if (e[i].x==A && e[j].y==B) sum=(sum+ans.num[i][j])%MOD; 
	printf("%d\n",sum);
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值