题目描述:
雾。
题目分析:
本题由 矩阵乘法路径数问题 转化得来
[HDU 2157]
给一个N个点,M条边的有向无权图,求出两点x,y间长度为t的路径总和(允许重复经过),也就是说,从x出发走t步到y的方案数
很明显,你可以考虑dp
设f[i][j][n]表示i出发现在走了n个时刻到j的方案数
a是邻接矩阵
f[i][j][n]=∑a[k][j]×f[i][k][n−1]f[i][j][n]=∑a[k][j]×f[i][k][n−1]
f[i][i][0]=1,f[i][j][1]=a[i][j]f[i][i][0]=1,f[i][j][1]=a[i][j]
然后观察式子,事实上这个答案只和邻接矩阵有关
f[i][j][n]=∑f[i][k][n−1]∗f[k][j][1]f[i][j][n]=∑f[i][k][n−1]∗f[k][j][1]
咦,这不就是矩阵乘法么
显然n就是指数
关于本题,我们考虑化边为点,然后当某条边的起点==另一条边的终点时,证明有链接。
题目链接:
Ac 代码:
// luogu-judger-enable-o2
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define mod 45989
int n,m,A,B,t;
struct Matrix{
int a[150][150];
int n,m;
Matrix()
{
memset(a,0,sizeof(a));
n=m=0;
}
};
inline Matrix operator * (Matrix t1,Matrix t2)
{
Matrix ans;
ans.n=t1.n,ans.m=t2.m;
for(int i=0;i<t1.n;i++)
for(int j=0;j<t2.m;j++)
for(int k=0;k<t1.m;k++)
ans.a[i][j]=(ans.a[i][j]+t1.a[i][k]*t2.a[k][j])%mod;
return ans;
}
inline Matrix ksm (Matrix ans,Matrix x,int y)
{
for(;y;y>>=1,x=x*x)
if(y&1) ans=ans*x;
return ans;
}
int u[1010];
int main()
{
scanf("%d%d%d%d%d",&n,&m,&t,&A,&B);
for(int i=0;i<m;i++)
scanf("%d%d",&u[(i<<1)|1],&u[(i<<1)]);
Matrix ans,b;
ans.n=2*m,ans.m=2*m;
b.n=2*m,b.m=2*m;
for(int i=0;i<2*m;i++)
for(int j=0;j<2*m;j++)
if((u[i]==u[j^1])&&((i>>1)!=(j>>1))) b.a[i][j]=1;
for(int i=0;i<2*m;i++)
if(u[i]==A) ans.a[0][i^1]=1;
ans=ksm(ans,b,t-1);
int Ans=0;
for(int i=0;i<2*m;i++)
if(u[i]==B)
Ans=(Ans+ans.a[0][i])%mod;
printf("%d\n",Ans);
return 0;
}