• [BZOJ]1297: [SCOI2009]迷路


    题目大意:给定一个有n个点的图的邻接矩阵,边权范围1~9,问从点0走到点n-1恰好走了长为T的路径的方案数。(n<=10,T<=10^9)

    思路:由于边权较小,我们把每个点拆成9个点,分别为该点,离该点距离还差1,还差2……还差8,这样我们就可以把原图重构成一个边权均为1的图。用f[i][j]表示走了长为i的路径之后到点j(重构后的)的方案数,则f[i]=f[i-1]*新的邻接矩阵,矩阵乘法快速幂加速DP即可,复杂度O((9n)^3*logT)。

    #include<cstdio>
    #include<cstring>
    #define MN 10
    #define ML 90
    #define MOD 2009
    struct mat
    {
        int z[ML][ML];
        mat operator*(mat b)
        {
            mat c;int i,j,k;
            memset(c.z,0,sizeof(c.z));
            for(i=0;i<ML;++i)for(k=0;k<ML;++k)if(z[i][k])
                for(j=0;j<ML;++j)c.z[i][j]=(c.z[i][j]+z[i][k]*b.z[k][j])%MOD;
            return c;
        }
    }ans,t;
    char g[MN+5][MN+5];
    int main()
    {
        int n,m,i,j;
        scanf("%d%d",&n,&m);
        for(i=0;i<n;++i)scanf("%s",g[i]);
        for(i=0;i<n;++i)
        {
            for(j=1;j<9;++j)t.z[i*9+j][i*9+j-1]=1;
            for(j=0;j<n;++j)if(g[i][j]>'0')t.z[i*9][j*9+g[i][j]-'1']=1;
        }
        for(ans.z[0][0]=1;m;m>>=1,t=t*t)if(m&1)ans=ans*t;
        printf("%d",ans.z[0][n*9-9]);
    }
  • 相关阅读:
    hdu 2001 计算两点的距离
    hdu 2001 计算两点的距离
    hdu 2000 ASCII码排序(c语言)
    hdu 2000 ASCII码排序(c语言)
    1.网页学习-开始学习第一步:
    .net 父窗口线程交给子窗口
    多线程传递多个参数
    not Exists的使用方法
    xml.dom.minidom介绍
    .net之线程控件之间访问
  • 原文地址:https://www.cnblogs.com/ditoly/p/BZOJ1297.html
Copyright © 2020-2023  润新知