zoukankan      html  css  js  c++  java
  • P4159 [SCOI2009] 迷路

    Problem

    给一个(n)个节点(m)条边的带权有向图。求从(1 o n)的长度为(t)的路径条数。对(2009)取模。
    (2 le n le 10,1 le t le 10^9)
    值得一提的是,此题的输入格式:

    说明边权(le 9)

    Solution

    Thinking 1

    考虑边权都为(1)怎么做。
    (f[t][i][j])为长度为(t)(i o j)的路径数。
    易得:

    [f[t][i][j] = sum_{k = 1} ^ n f[t - 1][i][k] cdot f[1][k][j] ]

    这就是矩阵乘法板子。易得(f[t] = f[1]^t)

    Thinking 2

    考虑一条(u o v),长度为(w)的边。
    可以把它拆成(w)条长度为(1)的边,然后中间用拆的点表示。
    然后变成(10n cdot 10n)的矩阵搞。

    # include <bits/stdc++.h>
    using namespace std;
    const int mod = 2009;
    int n,t;
    struct Matrix
    {
        int a[105][105];
        void init(int x = 0)
        {
            for(int i = 1; i <= n * 10; i++)
            {
                for(int j = 1; j <= n * 10; j++) 
                {
                    a[i][j] = (i == j) ? x : 0;
                }
            }
            return;
        }
    }A;
    int calc(int i,int j) {return (i - 1) * 10 + j;}
    Matrix operator * (const struct Matrix &x,const struct Matrix &y)
    {
        Matrix ans; ans.init();
        for(int i = 1; i <= n * 10; i++)
        {
            for(int j = 1; j <= n * 10; j++)
            {
                for(int k = 1; k <= n * 10; k++)
                {
                    ans.a[i][j] = (ans.a[i][j] + x.a[i][k] * y.a[k][j]) % mod;
                }
            }
        }
        return ans;
    }
    Matrix qpow(Matrix x,int p)
    {
        Matrix ans; ans.init(1);
        while(p)
        {
            if(p & 1) ans = ans * x;
            p >>= 1;
            x = x * x;
        }
        return ans;
    }
    int main(void)
    {
        scanf("%d%d",&n,&t);
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= 9; j++)
            {
                A.a[calc(i,j)][calc(i,j + 1)] = 1;
            }
        }
        for(int i = 1; i <= n; i++)
        {
            char s[12];
            scanf("%s", s + 1);
            for(int j = 1; j <= n; j++)
            {
                int x = s[j] - '0';
                if(!x) continue;
                A.a[calc(i,x)][calc(j,1)] = 1;
            }
        }
        Matrix ans = qpow(A,t);
        printf("%d
    ",ans.a[1][calc(n,1)]);
        return 0;
    }
    
  • 相关阅读:
    读写配置文件app.config
    UML类图
    我见到James Rumbaugh了!
    获取数据库中的所有表
    通过DataTable获得表的主键
    用例的本质
    用例图
    使用SQLDMO中“接口SQLDMO.Namelist 的 QueryInterface 失败”异常的解决方法
    类如何与界面绑定
    C#使用指针
  • 原文地址:https://www.cnblogs.com/luyiming123blog/p/15139281.html
Copyright © 2011-2022 走看看