×

第十二篇:P2151

题解补完计划:第十二篇。

原题题面

显然,DP 时间 \(O(t)\),爆炸,考虑矩阵优化,显然,转移就是向有连边的转移,时间 \(O(m^3 \log t)\),注意是左乘矩阵还是右乘矩阵。

#include<bits/stdc++.h>
using namespace std;
#define N 65
#define mod 45989
#define intl long long
#define inf 1145141919810ll
#define For(i,a,b) for(intl i=a;i<=b;i++)
#define deo(i,a,b) for(intl i=a;i>=b;i--)
intl read() {
	intl x=0,k=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch == '-') k=-1;ch=getchar();}
	while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*k;
}
void write(intl x) {
	if(x < 0) putchar('-'),x*=-1;
	if(x > 9) write(x/10);
	putchar('0'+x%10);
}
struct node{
	intl to,nxt;
}e[N<<1];
intl cnt,h[N];
intl n,m,S,E,t;
struct matrix {
	intl a[N<<1][N<<1];
	matrix operator * (const matrix&b) const {
		matrix ans;
		memset(ans.a,0,sizeof ans.a);
		For(i,0,cnt-1) For(k,0,cnt-1) if(a[i][k]) For(j,0,cnt-1) 
		(ans.a[i][j] += a[i][k]*b.a[k][j]) %= mod;
		return ans;
	}
}mat,qwe;
matrix matpow(matrix a,intl b) {
	matrix ans;
	memset(ans.a,0,sizeof ans.a);
	For(i,0,cnt-1) ans.a[i][i]=1;
	while(b) {
		if(b&1) ans = ans*a;
		a=a*a;b>>=1;
	}
	return ans;
}
void add(intl from,intl to) {e[cnt]={to,h[from]};h[from]=cnt++;}
intl idx,id[N];
int main() {
	memset(h,-1,sizeof h);
	n=read(),m=read(),t=read(),S=read()+1,E=read()+1;
	memset(mat.a,0,sizeof mat.a);
	For(i,1,m) {
		intl u=read()+1,v=read()+1;
		add(u,v);add(v,u);
	}
	For(i,0,cnt-1) {
		for(intl j=h[e[i].to];~j;j=e[j].nxt) {
			if((i^1)!=j) mat.a[j][i]++;
		}
	}
	for(intl i=h[S];~i;i=e[i].nxt) qwe.a[i][1]++;
	mat = matpow(mat,t-1)*qwe;
	intl ans=0;
	for(intl i=h[E];~i;i=e[i].nxt) (ans += mat.a[i^1][1]) %= mod;
	printf("%lld ",ans);
	return 0;
}
/*

*/
posted @ 2026-10-05 17:28  shiori123  阅读(5)  评论(0)    收藏  举报