第十二篇: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;
}
/*
*/

浙公网安备 33010602011771号