SSL 2511/bzoj 1898 沼泽鳄鱼 矩阵乘法
题目大意
给一个无向图,起点和终点(stand,end)。从起点到终点,要走过t条边(t给定)。每条边的权值都是单位1。一些点中会有食人鱼,食人鱼会在k(2<=k<=4)个点之间循环,当循环到改点时则不能待在改点上。求从起点恰好走完t个单位时间后到达终点的路径条数。
分析
用矩阵乘法解此题。在没有食人鱼时,直接建立邻接矩阵A,然后求从起点到终点的方案数。A^t,输出A[s,e]即可。
但现在有了食人鱼。观察后发现,一条食人鱼的活动周期只可能是2,3,4,所以所有的食人鱼的一个大的活动周期是12(2,3,4的最小公倍数)。即,我们可以推出12个时刻的邻接矩阵(f[1],f[2],f[3]…f[12])(表示此时刻可以走的点和路)。然后,把十二个矩阵相乘得到矩阵A,再求A^(t div 12)。
因为t/12会有余数,设余数为x,就代表还有x个时刻没算,所以A要乘f[1],f[2]...f[x]。最后输出A[s,e] mod 10000,即可。
<span style="font-size:12px;font-weight: normal;">
type arr=array[0..100,0..100] of longint; var a:array[1..100] of arr; d:array[1..100,0..10] of longint; n,m,f:longint; x,y:longint; ans:int64; i,j,k,l:longint; function cheng(x,x1:arr):arr; var i,j,k:longint; begin fillchar(cheng,sizeof(cheng),0); for i:=1 to n do for j:=1 to n do for k:=1 to n do cheng[i,j]:=(cheng[i,j]+x[i,k]*x1[k,j]) mod 10000; end; procedure seach(n:longint); var i,j,k:longint; begin if n=0 then exit; seach(n div 2); a[15]:=cheng(a[15],a[15]); if n mod 2=1 then a[15]:=cheng(a[15],a[13]); end; begin readln(n,m,x,y,ans); for i:=1 to m do begin readln(j,k); j:=j+1; k:=k+1; a[13,j,k]:=1; a[13,k,j]:=1; end; readln(f); for i:=1 to f do begin read(j); for k:=1 to j do begin read(d[i,k]); d[i,k]:=d[i,k]+1; end; d[i,0]:=j; readln; end; for i:=1 to 12 do a[i]:=a[13]; for i:=1 to f do begin for j:=1 to 12 do begin l:=j mod d[i,0]; if l=0 then l:=d[i,0]; for k:=1 to n do a[j][d[i,l]][k]:=0; end; end; for i:=1 to n do a[15][i][i]:=1; for i:=1 to 12 do a[15]:=cheng(a[15],a[i]); a[13]:=a[15]; a[15]:=a[16]; for i:=1 to n do a[15][i][i]:=1; seach(ans div 12); for i:=1 to ans mod 12 do a[15]:=cheng(a[15],a[i]); write(a[15][x+1][y+1] mod 10000); end.</span>