P4159 [SCOI2009]迷路
先考虑只有 01 边权的情况
显然可以DP+矩阵加速
但是现在边权不止 1
然鹅最大也只有 9
所以从这里入手,把点拆成 9 个,然后点之间的边权也就可以变成 1 了
同样的转移和矩阵加速
注意点之间的连接关系
#include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<cstring> using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } const int N=207,mo=2009; inline int fk(int x) { return x>=mo ? x-mo : x; } int n,T,m; struct matrix//矩阵乘法不解释 { int a[N][N]; matrix () { memset(a,0,sizeof(a)); } inline matrix operator * (const matrix &tmp) const { matrix res; for(int i=1;i<=m;i++) for(int j=1;j<=m;j++) for(int k=1;k<=m;k++) res.a[i][j]=fk(res.a[i][j]+a[i][k]*tmp.a[k][j]%mo); return res; } }F,M; matrix ksm(matrix X,int Y)//矩阵快速幂不解释 { matrix res; for(int i=1;i<=m;i++) res.a[i][i]=1; while(Y) { if(Y&1) res=res*X; X=X*X; Y>>=1; } return res; } char s[N]; int main() { n=read(); T=read(); m=n*9; for(int i=1;i<=n;i++)//构造转移矩阵 { int t=(i-1)*9+1; for(int j=1;j<9;j++) M.a[t+j][t+j-1]=1; scanf("%s",s+1); for(int j=1;j<=n;j++) { if(s[j]=='0') continue; M.a[t][(j-1)*9+s[j]-'0']=1; } } F.a[1][1]=1; F=F*ksm(M,T); printf("%d",F.a[1][(n-1)*9+1]); return 0; }