n个顶点的有向图,每条边的边权都在1~9。问从1到n的长度为t的路径有几条。
看时间10^9立即想到矩乘。而且n≤10,边权范围只有9。那么把每个点都拆成9个。构造01矩阵。
一个点拆成9个之后这9个点首先要连通。然后就是(u,v,w)的边,从(u,w)连一条边到(v,1),最后答案就是Matrix[1][(n,1)]。
复杂度:O(81*n^3*log(t))。rank5、、呵呵、、还不慢、、
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define pos(x,y) (9*((x)-1)+y) struct matrix{ int r,c,num[95][95]; matrix(){memset(num,0,sizeof(num));}; matrix(int _r,int _c):r(_r),c(_c){memset(num,0,sizeof(num));}; inline void setone(){ for(int i=1;i<=r;i++) num[i][i]=1;} matrix operator * (matrix b)const{ matrix d(r,b.c); for(int i=1;i<=r;i++) for(int j=1;j<=b.c;j++){ for(int k=1;k<=c;k++) d.num[i][j]+=num[i][k]*b.num[k][j]; d.num[i][j]%=2009; }return d; } }A; int n,t; char s[12]; matrix operator ^(matrix a,int b){ matrix d(a.r,a.c); d.setone(); while(b){ if(b&1) d=d*a; b>>=1; a=a*a;} return d; }int main(){ scanf("%d%d",&n,&t); A.r=A.c=9*n; for(int i=1;i<=n;i++) for(int j=1;j<=8;j++) A.num[pos(i,j)][pos(i,j+1)]=1; for(int i=1;i<=n;i++){ scanf("%s",s+1); for(int j=1;j<=n;j++) if(s[j]-'0') A.num[pos(i,s[j]-'0')][pos(j,1)]=1; }printf("%d\n",(A^t).num[1][pos(n,1)]); return 0; }