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,即可。


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.


转载于:https://www.cnblogs.com/a-loud-name/p/6184841.html

你可能感兴趣的:(SSL 2511/bzoj 1898 沼泽鳄鱼 矩阵乘法)