bzoj-4887-dp+矩阵快速幂

4887: [Tjoi2017]可乐

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 247  Solved: 170
[Submit][Status][Discuss]

Description

加里敦星球的人们特别喜欢喝可乐。因而,他们的敌对星球研发出了一个可乐机器人,并且
放在了加里敦星球的1号城市上。这个可乐机器人有三种行为:停在原地,去下一个相邻的
城市,自爆。它每一秒都会随机触发一种行为。现在给出加里敦星球城市图,在第0秒时可
乐机器人在1号城市,问经过了t秒,可乐机器人的行为方案数是多少?
 

Input

第一行输入两个正整数N,M表示城市个数,M表示道路个数。(1≤N≤30,0≤M≤100)
接下来M行输入u,v表示u,v之间有一条道路。
(1≤u,v≤n)保证两座城市之间只有一条路相连。
最后输入时间t。1<t≤10^6

Output

 输出可乐机器人的行为方案数,答案可能很大,请输出对2017取模后的结果。

Sample Input

3 2
1 2
2 3
2

Sample Output

 

    f[i][j][0/1]表示在i时刻,处于j位置,0表示存活,1表示爆炸的方案个数,f[i][j][0]->f[i+1][j][0],f[i+1][adj[k]][0],f[i+1][j][1] ,f[i][j][1]不能转移因为已经爆炸了。每一秒的状态都只由上一秒决定,考虑使用快速幂加速,(f[i][1][0],f[i][2][0]......f[i][n][0],Si)*A=(f[i+1][1][0],f[i+1][2][0]......f[i+1][n][0],Si+1),A实际上就是表示点的可达关系的矩阵,A[i][j]表示i->j可达,Si表示当前累计 SUM{f[1][][1]+f[2][][1]+...+f[i][][1]},只要把原先N*N的矩阵扩张为(N+1)*(N+1)就好了,最后一列全置1。

    

 1 #include<iostream>
 2 #include<cstring>
 3 #include<queue>
 4 #include<cstdio>
 5 #include<stack>
 6 #include<set>
 7 #include<map>
 8 #include<cmath>
 9 #include<ctime>
10 #include<time.h> 
11 #include<algorithm>
12 #include<bits/stdc++.h>
13 using namespace std;
14 #define mp make_pair
15 #define pb push_back
16 #define debug puts("debug")
17 #define LL  long long 
18 #define ULL unsigned long long 
19 #define uint unsigned int
20 #define pii pair<int,int>
21 #define eps 1e-10
22 #define inf 0x3f3f3f3f
23  
24 struct matrix{
25     int len;
26     int a[35][35];
27     matrix(){
28         memset(a,0,sizeof(a));
29     }
30     matrix& operator*(matrix& tmp){
31         matrix ans;
32         ans.len=len;
33         for(int i=1;i<=len;++i){
34             for(int j=1;j<=len;++j){
35                 for(int k=1;k<=len;++k){
36                     ans.a[i][k]+=a[i][j]*tmp.a[j][k];
37                     ans.a[i][k]%=2017;
38                 }
39             }
40         }
41         return ans;
42     }
43     
44 }A,I;
45 matrix qpow(matrix X,int n){
46     matrix ans=I;
47     while(n){
48         if(n&1) ans=ans*X;
49         X=X*X;
50         n>>=1;
51     }
52     return ans;
53 }
54 int main(){
55     int n,m,i,j,k,t;
56     scanf("%d%d",&n,&m);
57     A.len=I.len=n+1;
58     for(i=1;i<=n+1;++i) A.a[i][i]=I.a[i][i]=1;
59     int u,v;
60     while(m--){
61         scanf("%d%d",&u,&v);
62         A.a[u][v]=1;
63         A.a[v][u]=1;
64     }
65     for(i=1;i<=n+1;i++)A.a[i][n+1]=1;
66     scanf("%d",&t);
67     cout<<qpow(A,t+1).a[1][n+1]<<endl;
68     return 0;
69 }

 

posted @ 2018-05-14 11:29  *zzq  阅读(164)  评论(0编辑  收藏  举报