[TJOI 2017]可樂
阿新 • • 發佈:2017-10-03
個數 多少 spa $1 矩陣加速 的人 des set 總數
Description
加裏敦星球的人們特別喜歡喝可樂。因而,他們的敵對星球研發出了一個可樂機器人,並且放在了加裏敦星球的1號城市上。這個可樂機器人有三種行為: 停在原地,去下一個相鄰的城市,自爆。它每一秒都會隨機觸發一種行為。現 在給加裏敦星球城市圖,在第0秒時可樂機器人在1號城市,問經過了t秒,可樂機器人的行為方案數是多少?Input
第一行輸入兩個正整數況N,M,N表示城市個數,M表示道路個數。(1 <= N <=30,0 < M < 100)
接下來M行輸入u,v,表示u,v之間有一條道路。(1<=u,v <= n)保證兩座城市之間只有一條路相連。
最後輸入入時間t
Output
輸出可樂機器人的行為方案數,答案可能很大,請輸出對2017取模後的結果。Sample Input
3 2
1 2
2 3
2
Sample Output
8
HINT
【樣例解釋】
1 ->爆炸
1 -> 1 ->爆炸
1 -> 2 ->爆炸
1 -> 1 -> 1
1 -> 1 -> 2
1 -> 2 -> 1
1 -> 2 -> 2
1 -> 2 -> 3
【數據範圍】 對於20%的pn,有1 < t ≤ 1000
對於100%的pn,有1 < t ≤ 10^6。
題解
考慮樸素的$DP$:
$f[i][j][0]$表示第$i$時刻,在城市$j$爆炸的方案數,$f[i][j][1]$表示第i時刻,在城市$j$不爆炸的方案數
$f[i][j][0]=f[i-1][j][0]+f[i-1][j][1]$,$f[i][j][1]=f[i][j][1]+f[i][k][1]$($k$是$j$的相鄰結點)
這樣是要$MLE$的,顯然狀態的答案只與前一狀態相關,直接滾動即可
可是依舊$T$了。
我們發現是城市數量很少,用鄰接矩陣存。有矩陣的話就可以矩陣加速了。
我們定義矩陣$S$為$1*(n+1)$答案矩陣,$S[0][0]$表示$t$秒前(包括$t$秒)爆炸的方案總數;$S[0][i]$,$1<=i<=n$表示$t$秒時在點$i$的方案總數,初始$S[0][1]=1$;
矩陣$T$為$(n+1)*(n+1)$的鄰接矩陣,除此之外:註意$T[i][0]=1$,$0<=i<=n$為了統計“爆炸”的情況;$T[i][i]=1$表示停在$i$點不動。
顯然我們需要$S*=T^t$,最後答案就是$\sum _{i=0} ^n S[0][i]$。
1 //It is made by Awson on 2017.10.3 2 #include <set> 3 #include <map> 4 #include <cmath> 5 #include <ctime> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <cstdio> 10 #include <string> 11 #include <cstring> 12 #include <cstdlib> 13 #include <iostream> 14 #include <algorithm> 15 #define LL long long 16 #define Max(a, b) ((a) > (b) ? (a) : (b)) 17 #define Min(a, b) ((a) < (b) ? (a) : (b)) 18 #define sqr(x) ((x)*(x)) 19 #define insert INSERT 20 using namespace std; 21 const int MOD = 2017; 22 void read(int &x) { 23 char ch; bool flag = 0; 24 for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == ‘-‘)) || 1); ch = getchar()); 25 for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar()); 26 x *= 1-2*flag; 27 } 28 29 int n, m, u, v, t; 30 struct mat { 31 int a[35][35]; 32 mat () { 33 memset(a, 0, sizeof(a)); 34 } 35 mat (int _a[35][35]) { 36 for (int i = 0; i <= n; i++) 37 for (int j = 0; j <= n; j++) 38 a[i][j] = _a[i][j]; 39 } 40 mat operator * (const mat &b) const{ 41 mat ans; 42 for (int i = 0; i <= n; i++) 43 for (int j = 0; j <= n; j++) 44 for (int k = 0; k <= n; k++) 45 (ans.a[i][j] += a[i][k]*b.a[k][j]) %= MOD; 46 return ans; 47 } 48 }S, T; 49 50 void work() { 51 read(n), read(m); 52 for (int i = 1; i <= m; i++) { 53 read(u), read(v); 54 T.a[u][v] = T.a[v][u] = 1; 55 } 56 for (int i = 0; i <= n; i++) 57 T.a[i][0] = T.a[i][i] = 1; 58 S.a[0][1] = 1; 59 read(t); 60 while (t) { 61 if (t&1) S = S*T; 62 t >>= 1; 63 T = T*T; 64 } 65 int ans = 0; 66 for (int i = 0; i <= n; i++) 67 (ans += S.a[0][i]) %= MOD; 68 printf("%d\n", ans); 69 } 70 int main() { 71 work(); 72 return 0; 73 }
[TJOI 2017]可樂