1. 程式人生 > >[SDOI2009]HH去散步(矩陣)

[SDOI2009]HH去散步(矩陣)

ems 矩陣乘法 c++ truct 輸入格式 限制 沒有 其中 max

題目描述

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。

輸出格式:

一行,表示答案。

輸入輸出樣例

輸入樣例#1: 復制
4 5 3 0 0
0 1
0 2
0 3
2 1
3 2
輸出樣例#1: 復制
4

說明

對於30%的數據,N ≤ 4,M ≤ 10,t ≤ 10。

對於100%的數據,N ≤ 50,M ≤ 60,t ≤ 2^30,0 ≤ A,B



神題。。。

為限制不走上一次來的路和可以矩陣加速,花邊位點,一條邊和邊s連邊當接近當s^1不是自己,這樣以邊做矩陣乘法1次可以走兩步,t-1次走t步



 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include"bits/stdc++.h"
 5 #define Rep(i,s,t) for(int i=s;i<=t;i++)
 6 
 7 using namespace std;
 8 
 9 const
int maxx = 120 + 5; 10 const int p = 45989; 11 12 int n,m,t,B,E,cnt=1,x,y,sum; 13 int head[maxx],nxt[maxx],to[maxx]; 14 15 void Add(int x,int y){ 16 nxt[++cnt]=head[x];to[cnt]=y;head[x]=cnt; 17 } 18 19 namespace matrix_mul{ 20 struct mat{ 21 int x[maxx][maxx]; 22 mat(){memset(x,0,sizeof(x));} 23 }; 24 25 mat mul(mat a,mat b){ 26 mat tmp;Rep(i,1,m*2+1) Rep(j,1,m*2+1) Rep(k,1,m*2+1) 27 tmp.x[i][j] = (tmp.x[i][j]+a.x[i][k]*b.x[k][j])%p; 28 return tmp; 29 } 30 31 mat pwr(mat a,int n){ 32 mat ans = a,tmp = a;n--; 33 while(n){if(n&1) ans=mul(ans,tmp);tmp=mul(tmp,tmp);n>>=1;} 34 return ans; 35 } 36 } 37 38 int main(){ 39 using namespace matrix_mul; 40 mat Ans,tmp; 41 scanf("%d%d%d%d%d",&n,&m,&t,&B,&E);B++;E++; 42 Rep(i,1,m) scanf("%d%d",&x,&y),x++,y++,Add(x,y),Add(y,x); 43 for(int i=head[B];i;i=nxt[i]) Ans.x[1][i]=1; 44 for(int i=2;i<=cnt;i++) 45 for(int j=head[to[i]];j;j=nxt[j]) 46 if(i != (j^1)) 47 tmp.x[i][j]++; 48 tmp = pwr(tmp,t-1); 49 50 51 for(int i=head[B];i;i=nxt[i]) 52 { 53 for (int j=2;j<=cnt;j++)if(to[j]==E)sum+=tmp.x[i][j],sum%=p; 54 } 55 cout<<sum<<endl; 56 return 0; 57 58 Ans = mul(Ans,tmp); 59 60 61 for(int i=2;i<=cnt;i++) 62 if(to[i]==E) 63 sum=(sum+Ans.x[1][i])%p; 64 65 printf("%d",sum); 66 return 0; 67 }

[SDOI2009]HH去散步(矩陣)