[SDOI2009]HH去散步
[SDOI2009]HH去散步
题目描述
HH有个一成不变的习惯,喜欢饭后百步走。所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离。 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回。 又因为HH是个喜欢变化的人,所以他每天走过的路径都不完全一样,他想知道他究竟有多 少种散步的方法。
现在给你学校的地图(假设每条路的长度都是一样的都是1),问长度为t,从给定地 点A走到给定地点B共有多少条符合条件的路径
输入输出格式
输入格式:
第一行:五个整数N,M,t,A,B。其中N表示学校里的路口的个数,M表示学校里的 路的条数,t表示HH想要散步的距离,A表示散步的出发点,而B则表示散步的终点。
接下来M行,每行一组Ai,Bi,表示从路口Ai到路口Bi有一条路。数据保证Ai != Bi,但 不保证任意两个路口之间至多只有一条路相连接。 路口编号从0到N − 1。 同一行内所有数据均由一个空格隔开,行首行尾没有多余空格。没有多余空行。 答案模45989。
输出格式:
一行,表示答案。
输入输出样例
说明
对于30%的数据,N ≤ 4,M ≤ 10,t ≤ 10。
对于100%的数据,N ≤ 50,M ≤ 60,t ≤ 2^30,0 ≤ A,B
思路
和迷路那道题相似,不过这一次我们不可以来回走
于是我们只好以x边的起点,y边的终点构造矩阵
然后就是同样的套路了,只不过我们需要在初始的时候加一个两条边是否为同一条边的条件,并且将t--,原因
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define rep(i,a,b) for(long long i=a;i<=b;i++) using namespace std; typedef long long ll; const ll mod=45989ll; ll n,mm,s,e,t,to[200],tot=-1,sum; struct zlk{ll M[200][200];}a,ans; zlk mul(zlk x,zlk y){ zlk rk; rep(i,0,tot) rep(j,0,tot) rk.M[i][j]=0; rep(i,0,tot) rep(j,0,tot) rep(k,0,tot){ rk.M[i][j]+=x.M[i][k]*y.M[k][j];rk.M[i][j]%=mod; } return rk; } void ksm(){ while(t){ if(t&1) ans=mul(ans,a); a=mul(a,a); t>>=1; } } int main(){ scanf("%lld%lld%lld%lld%lld",&n,&mm,&t,&s,&e); s++; e++; t--; rep(i,1,mm){ ll x,y; scanf("%lld%lld",&x,&y); x++; y++; to[++tot]=y; to[++tot]=x; } rep(i,0,tot) rep(j,0,tot) if(to[i]==to[(j^1)] && i!=(j^1)) a.M[i][j]=1; rep(i,0,tot) ans.M[i][i]=1; ksm(); rep(i,0,tot) rep(j,0,tot) if(to[(i^1)]==s && to[j]==e) sum=(sum+ans.M[i][j])%mod; printf("%lld",sum); return 0; }