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。
输出格式:
一行,表示答案。
样例输入:
4 5 3 0 0
0 1
0 2
0 3
2 1
3 2
样例输出:
4
数据范围:
对于30%的数据,N ≤ 4,M ≤ 10,t ≤ 10。
对于100%的数据,N ≤ 20,M ≤ 60,t ≤ 230,0 ≤ A,B<N,0 ≤ Ai,Bi <N。
如果抛开不能走刚刚走过的路径的条件就是十分基础的矩阵乘法了
因为有这个条件,所以矩阵改为(2m)*(2m)的
之所以是2m的是把m条无向边拆为2m条有向边
矩阵(i,j)位置的数表示第一次走i号路,最后一次走j号路的方案数
program walker;
const
maxn=45989;
type
square=array [1..120,1..120] of longint;
var
sum,n,m,i,j,k,u,v,t,a,b:longint;
line:array [0..121] of record
u,v:longint;
end;
ans,root:square;
function anti (now:longint):longint;
begin
if now<=m then exit(now+m)
else exit(now-m);
end;
function matrixmul (a,b:square):square;
var
i,j,k:longint;
ans:square;
begin
fillchar(ans,sizeof(ans),0);
for i:=1 to 2*m do
for j:=1 to 2*m do
for k:=1 to 2*m do
ans[i,j]:=(ans[i,j]+a[i,k]*b[k,j]) mod maxn;
exit(ans);
end;
begin
assign(input,'walker.in');
reset(input);
assign(output,'walker.out');
rewrite(output);
read(n,m,t,a,b);
inc(a);
inc(b);
for i:=1 to m do
begin
read(u,v);
inc(u);
inc(v);
line[i].u:=u;
line[i].v:=v;
line[i+m].u:=v;
line[i+m].v:=u;
end;
for i:=1 to 2*m do
ans[i,i]:=1;
for i:=1 to 2*m do
for j:=1 to 2*m do
if (j<>anti(i))and(line[i].v=line[j].u) then inc(root[i,j]);
dec(t);
for i:=0 to 30 do
begin
if t or (1 shl i) = t then ans:=matrixmul(ans,root);
root:=matrixmul(root,root);
end;
sum:=0;
for i:=1 to 2*m do
for j:=1 to 2*m do
if (line[i].u=a)and(line[j].v=b) then sum:=(sum+ans[i,j]) mod maxn;
writeln(sum);
close(input);
close(output);
end.