【bzoj4887】:[Tjoi2017]可乐 矩阵乘法,快速幂

【bzoj4887】:[Tjoi2017]可乐

题目大意:一张无相连通图(n<=30),从1号点开始走,每秒可以走到相邻的点也可以自爆,求第t秒(t<=1e6)后所有的方案数是多少对2017取模

恩。。就是一个矩阵快速幂。。矩阵就是原图的邻接矩阵。。然后f[i][i]也是1。。

但是这是不会自爆的情况下的矩阵,算上自爆的话要把每次转移的结果求和。。蒟蒻想了半天。。

然后发现其实只要再加一行一列,然后f[n+1][i]=1,就可以了。。

意会一下好了。。矩阵什么的感觉讲不清楚啊。。

 1 /* http://www.cnblogs.com/karl07/ */
 2 #include <cstdlib>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <algorithm>
 7 using namespace std;
 8 
 9 struct MAT{
10     int m[35][35],x,y,sum;
11     MAT () {for (int i=0;i<35;i++) for (int j=0;j<35;j++) m[i][j]=0; sum=x=y=0;}
12 }a,b;
13 int n,m,t;
14 int mp[35][35];
15 
16 MAT operator *(const MAT &a,const MAT &b){
17     MAT c;
18     c.x=b.x;c.y=a.y;
19     for (int i=1;i<=c.x;i++){
20         for (int j=1;j<=c.y;j++){
21             c.m[i][j]=0;
22             for (int k=1;k<=a.x;k++){
23                 c.m[i][j]+=a.m[k][j]*b.m[i][k]%2017;
24                 c.m[i][j]%=2017;
25             }
26             c.sum+=c.m[i][j];
27             c.sum%=2017;
28         }
29     }
30     return c;
31 } 
32 
33 int main(){
34     scanf("%d%d",&n,&m);
35     a.x=n+1,a.y=1,a.m[1][1]=1;
36     b.x=b.y=n+1;
37     for (int i=1;i<=m;i++){
38         int p,q;
39         scanf("%d%d",&p,&q);
40         b.m[p][q]++;
41         b.m[q][p]++;
42     }
43     for (int i=1;i<=n+1;i++){
44         b.m[i][i]=1;
45         b.m[n+1][i]=1;
46     }
47     scanf("%d",&t);
48     while (t){
49         if (t&1) a=a*b;
50         b=b*b;
51         t=(t>>1);
52     }
53     printf("%d\n",a.sum);
54     return 0;
55 }
View Code

啊。。终于不是游记了。。

posted @ 2017-05-27 18:49  karl07  阅读(475)  评论(0编辑  收藏  举报