【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 }
啊。。终于不是游记了。。