BZOj-1875: [SDOI2009]HH去散步 (矩陣快速冪)
阿新 • • 發佈:2017-11-09
space ems def bbs bit 習慣 friend long while
Submit: 1999 Solved: 980
[Submit][Status][Discuss]
第一行:五個整數N,M,t,A,B。
N表示學校裏的路口的個數
M表示學校裏的 路的條數
t表示HH想要散步的距離
A表示散步的出發點
B則表示散步的終點。
接下來M行
每行一組Ai,Bi,表示從路口Ai到路口Bi有一條路。
數據保證Ai != Bi,但不保證任意兩個路口之間至多只有一條路相連接。
路口編號從0到N -1。
同一行內所有數據均由一個空格隔開,行首行尾沒有多余空格。沒有多余空行。
答案模45989。
N ≤ 20,M ≤ 60,t ≤ 2^30,0 ≤ A,B
0 1
0 2
0 3
2 1
3 2
1875: [SDOI2009]HH去散步
Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1999 Solved: 980
[Submit][Status][Discuss]
Description
HH有個一成不變的習慣,喜歡飯後百步走。所謂百步走,就是散步,就是在一定的時間 內,走過一定的距離。 但 是同時HH又是個喜歡變化的人,所以他不會立刻沿著剛剛走來的路走回。 又因為HH是個喜歡變化的人,所以他每 天走過的路徑都不完全一樣,他想知道他究竟有多 少種散步的方法。 現在給你學校的地圖(假設每條路的長度都 是一樣的都是1),問長度為t,從給定地 點A走到給定地點B共有多少條符合條件的路徑Input
Output
一行,表示答案。
Sample Input
4 5 3 0 00 1
0 2
0 3
2 1
3 2
Sample Output
4HINT
Source
Day1
laj一開始把題目看錯了= = 不能走回頭路哇……laj就說這題怎麽可能這麽傻逼呢…… 然後就是很神的做法咯……把邊存到矩陣裏收尾相接的兩條邊在矩陣裏連邊,然後求t-1次冪,在開另一個矩陣,剩下的開代碼qwq laj又忘記膜辣……wa了一發 _(:зゝ∠)_1 #include "bits/stdc++.h" 2 using namespace std; 3 typedef long long LL; 4 const int MAX=205,mod=45989; 5 int n,m,t,st,ed; 6struct Mat{ 7 int x,y; 8 int mat[MAX][MAX]; 9 Mat(){x=y=0;memset(mat,0,sizeof(mat));} 10 friend Mat operator * (Mat cc,Mat tt) { 11 Mat an;int i,j,k; 12 an.x=cc.x,an.y=tt.y; 13 for (i=1;i<=cc.x;i++) 14 for (k=1;k<=cc.y;k++) 15 if (cc.mat[i][k]) 16 for (j=1;j<=an.y;j++) 17 an.mat[i][j]=(an.mat[i][j]+cc.mat[i][k]*tt.mat[k][j])%mod; 18 return an; 19 } 20 friend Mat operator ^(Mat cc,int tt) { 21 Mat an;int i,j; 22 an.x=cc.x,an.y=cc.y; 23 for (i=1;i<=cc.x;i++) an.mat[i][i]=1; 24 while (tt){ 25 if (tt&1) an=an*cc; 26 cc=cc*cc,tt>>=1; 27 } 28 return an; 29 } 30 void out(){ 31 int i,j; 32 for (i=1;i<=x;i++){ 33 for (j=1;j<=y;j++) 34 printf("%d ",mat[i][j]); 35 printf("\n"); 36 } 37 printf("\n"); 38 } 39 }a,b; 40 struct Edge{int x,y;}edge[1005]; 41 int tot,head[MAX],adj[1005],next[1005]; 42 void addedge(int u,int v){tot++;adj[tot]=v,next[tot]=head[u],head[u]=tot,edge[tot].x=u,edge[tot].y=v;} 43 inline int read(){ 44 int an=0,x=1;char c=getchar(); 45 while (c<‘0‘ || c>‘9‘) {if (c==‘-‘) x=-1;c=getchar();} 46 while (c>=‘0‘ && c<=‘9‘) {an=(an<<3)+(an<<1)+c-‘0‘;c=getchar();} 47 return an*x; 48 } 49 int main(){ 50 freopen ("walk.in","r",stdin);freopen ("walk.out","w",stdout); 51 int i,j,x,y;tot=1; 52 n=read(),m=read(),t=read(),st=read(),ed=read();st++,ed++; 53 for (i=1;i<=m;i++){ 54 x=read(),y=read();x++,y++; 55 addedge(x,y),addedge(y,x); 56 } 57 a.x=a.y=b.x=b.y=tot; 58 for (i=head[st];i;i=next[i]) a.mat[1][i]++; 59 for (i=2;i<=tot;i++) 60 for (j=2;j<=tot;j++) 61 if (edge[i].y==edge[j].x && i!=(j^1)) 62 b.mat[i][j]++; 63 a=a*(b^(t-1)); 64 int ans=0; 65 for (i=head[ed];i;i=next[i]) 66 ans+=a.mat[1][i^1]; 67 printf("%d",ans%mod); 68 return 0; 69 }
BZOj-1875: [SDOI2009]HH去散步 (矩陣快速冪)