【Luogu】P4159迷路(矩阵优化)
将每个点拆成时刻1~9,然后根据题目要求连边,比如i-j有一条权为x的边就从点i-x向点j-1连一条边,表示经过x次之后可以到达。
然后就矩阵快速幂乱搞就好了。
#include<cstdio> #include<cstring> #include<algorithm> #include<cctype> #include<cstdlib> #define maxn 105 #define mod 2009 using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } int lim; struct Matrix{ long long s[maxn][maxn]; void clear(){memset(s,0,sizeof(s)); } }; Matrix operator *(Matrix a,Matrix b){ Matrix ans; ans.clear(); for(int i=1;i<=lim;++i) for(int j=1;j<=lim;++j) for(int k=1;k<=lim;++k) ans.s[i][j]=(ans.s[i][j]+a.s[i][k]*b.s[k][j]%mod)%mod; return ans; } Matrix Pow(Matrix a,long long b){ Matrix ret; ret.clear(); for(int i=1;i<=maxn;++i) ret.s[i][i]=1; while(b){ if(b&1) ret=ret*a; a=a*a; b>>=1; } return ret; } int n; int calc(int a,int b){ return a+(b-1)*n; } char c[maxn]; int main(){ Matrix sta; sta.clear(); n=read();long long t=read();lim=n*9; for(int i=1;i<=n;++i){ for(int j=1;j<9;++j) sta.s[calc(i,j)][calc(i,j+1)]++; scanf("%s",c+1); for(int j=1;j<=n;++j){ int x=c[j]-'0'; if(x==0) continue; for(int k=1;k+x-1<=9;++k) sta.s[calc(i,x+k-1)][calc(j,1+k-1)]++; } } sta=Pow(sta,t); //for(int i=1;i<=lim;++i,printf("\n")) // for(int j=1;j<=lim;++j) printf("%lld ",sta.s[i][j]); printf("%lld",sta.s[1][n]); return 0; }