bzoj-4887-dp+矩阵快速幂
4887: [Tjoi2017]可乐
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 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
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 }