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;
}

 

posted @ 2018-11-05 10:17  LLTYYC  阅读(218)  评论(0编辑  收藏  举报