• [bzoj1297][SCOI2009]迷路


    给定一个n个点的有向图,给定邻接矩阵,每条边的距离都是1-9,求从1号点走到n号点且距离恰好为T的方案数量%2009.   n<=10,T<=10^9

    题解:看到T的范围很容易想到矩阵乘法,但是距离不全是1没法搞,所以我们可以把每条边拆点,这样就保证了边权都是1,可以矩阵乘法啦

    但是这样的话点的数量有点多,最多n^2*9 ,也就是900个,直接搞还是T。

    但是我们发现我们没必要把每条边拿出来拆,只要对每个点拆出9个点,表示离这个点距离为0-8的点,就可以啦,这样点的数量V=n*9

    复杂度V^3*logT

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define mod 2009 
    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 * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int n,T;
    int f[15][15][35];
    char st[15];
    int id[15][15],tot=0;
    
    struct sq{
        int f[95][95];
        int n,m;
        sq operator *(sq y)
        {
            sq c;memset(c.f,0,sizeof(c.f));
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                    for(int k=1;k<=y.m;k++)
                        c.f[i][j]=(c.f[i][j]+f[i][k]*y.f[k][j])%mod;
            c.n=n;c.m=y.m;
            return c;
        }
    }s,s2;
    
    int main()
    {
        n=read();T=read(); 
        for(int i=1;i<=n;i++)
            for(int j=0;j<=8;j++)
            {
                id[i][j]=++tot;
                if(j)s.f[tot][tot-1]=1;    
            }
        s.n=s.m=tot;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",st+1);
            for(int j=1;j<=n;j++)
                if(st[j]!='0')
                    s.f[id[i][0]][id[j][st[j]-'1']]=1;
        }    
        s2.n=1;s2.m=tot;
        s2.f[1][id[1][0]]=1;
        for(;T;T>>=1,s=s*s)
            if(T&1) s2=s2*s;
        cout<<s2.f[1][id[n][0]];
        return 0;
    }
  • 相关阅读:
    Python 冒泡排序
    编程规范之注释篇
    编程规范之变量命名篇
    安装Django
    字典&列表的拓展理解
    小球落地
    Python结合sql登陆案例
    面向对象:两手交换牌
    每日一题(一)
    Web应用之LAMP源码环境部署
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj1297.html
Copyright © 2020-2023  润新知