1. 程式人生 > >P4159 [SCOI2009]迷路

P4159 [SCOI2009]迷路

pac lan 解釋 關系 getchar lin tor printf div

傳送門

先考慮只有 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; }

P4159 [SCOI2009]迷路