[SDOI2009] HH去散步 (矩阵乘法)
$solution:$
将边化为点后重新建矩阵,跑$T-1$幂即可(因为跑的是新边)。
最后直接找与$x,y$所相连的边即可。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define int long long #define mod 45989 using namespace std; inline int read(){ int f=1,ans=0;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } const int MAXN=101; struct Matrix{ int a[MAXN<<1][MAXN<<1]; void init(){memset(a,0,sizeof(a));return;} }F,G; int cnt,n,m,A,B,T,sta[MAXN][MAXN<<1],End[MAXN<<1]; Matrix operator*(Matrix x1,Matrix x2){ Matrix x3;x3.init(); for(int i=1;i<=(m<<1);i++) for(int k=1;k<=(m<<1);k++) for(int j=1;j<=(m<<1);j++) x3.a[i][j]+=x1.a[i][k]*x2.a[k][j],x3.a[i][j]%=mod; return x3; } Matrix ksm(Matrix a,int b){ Matrix ans;ans.init(); for(int i=1;i<=(m<<1);i++) ans.a[i][i]=1; while(b){ if(b&1) ans=ans*a; a=a*a,b>>=1; }return ans; }int ans; int uu[MAXN<<1],vv[MAXN<<1]; bool check(int idi,int idj){ if(vv[idi]==uu[idj]) return 1; return 0; } signed main(){ n=read(),m=read(),T=read(),A=read()+1,B=read()+1; for(int i=1;i<=m;i++){ int u=read()+1,v=read()+1; if(v==B) End[++End[0]]=i; if(u==B) End[++End[0]]=i+m; sta[u][++sta[u][0]]=i; uu[i]=u,vv[i]=v; sta[v][++sta[v][0]]=i+m; uu[i+m]=v,vv[i+m]=u; }F.init(),G.init(); for(int i=1;i<=(m<<1);i++){ for(int j=1;j<=(m<<1);j++) if(check(i,j)&&(i+m!=j&&j+m!=i)) G.a[i][j]=1; } //print(G); //printf("=========================\n"); F=ksm(G,T-1); //print(F); //for(int i=1;i<=End[0];i++) printf("End(%d):%d\n",i,End[i]); //for(int i=1;i<=sta[A][0];i++) printf("sta(%d):%d\n",i,sta[A][i]); for(int i=1;i<=sta[A][0];i++) for(int j=1;j<=End[0];j++) ans+=F.a[sta[A][i]][End[j]],ans%=mod; printf("%lld\n",ans); }