[Luogu P4159] [BZOJ 1297] [SCOI2009]迷路

版权声明:欢迎转载蒟蒻博客,但请注明出处: https://blog.csdn.net/LPA20020220/article/details/84288049

洛谷传送门

BZOJ传送门

题目描述

windy在有向图中迷路了。 该有向图有 N N 个节点,windy从节点 0 0 出发,他必须恰好在 T T 时刻到达节点 N 1 N-1 。 现在给出该有向图,你能告诉windy总共有多少种不同的路径吗? 注意:windy不能在某个节点逗留,且通过某有向边的时间严格为给定的时间。

输入输出格式

输入格式:

第一行包含两个整数, N   T N\ T 。 接下来有 N N 行,每行一个长度为 N N 的字符串。 第 i i 行第 j j 列为 0 0 表示从节点 i i 到节点 j j 没有边。 为 1 1 9 9 表示从节点 i i 到节点 j j 需要耗费的时间。

输出格式:

包含一个整数,可能的路径数,这个数可能很大,只需输出这个数除以 2009 2009 的余数。

输入输出样例

输入样例#1:

2 2
11
00

输出样例#1:

1

输入样例#2:

5 30
12045
07105
47805
12024
12345

输出样例#2:

852

说明

【样例解释一】

0->0->1

【数据范围】

30 % 30\% 的数据,满足 2 N 5 2 \le N \le 5 1 T 30 1 \le T \le 30

100 % 100\% 的数据,满足 2 N 10 2 \le N \le 10 1 T 1000000000 1 \le T \le 1000000000

解题分析

如果是 0 / 1 0/1 矩阵, 直接举证快速幂就好了, 然而这道题有边权…

那就把每个点拆成 9 9 个, 暴力连边跑矩乘就好了。

代码如下:

#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#define R register
#define MOD 2009
#define IN inline
#define W while
#define gc getchar()
#define MX 120
int n, bd;
long long T;
struct Matrix {int dat[MX][MX];} ans, mp;
IN Matrix operator * (const Matrix &x, const Matrix &y)
{
    Matrix ret;
    std::memset(ret.dat, 0, sizeof(ret.dat));
    for (R int i = 1; i <= bd; ++i)
    for (R int j = 1; j <= bd; ++j)
    for (R int k = 1; k <= bd; ++k)
    ret.dat[i][j] = (ret.dat[i][j] + x.dat[i][k] * y.dat[k][j] % MOD) % MOD;
    return ret;
}
IN void qpow()
{
    for (R int i = 1; i <= bd; ++i) ans.dat[i][i] = 1;
    W(T)
    {
        if(T & 1) ans = ans * mp;
        mp = mp * mp, T >>= 1;
    }
}
char buf[20];
int main(void)
{
     scanf("%d%lld", &n, &T); bd = n * 9;
     for (R int i = 1; i <= n; ++i)
     for (R int j = 1; j <= 8; ++j)
     mp.dat[(i - 1) * 9 + j][(i - 1) * 9 + j + 1] = 1;
     for (R int i = 1; i <= n; ++i)
     {
     	scanf("%s", buf + 1);
     	for (R int j = 1; j <= n; ++j)
     	{
     		if(buf[j] != '0')
     		mp.dat[(i - 1) * 9 + buf[j] - '0'][(j - 1) * 9 + 1] = 1;
     	}
     }
     qpow();
     printf("%d", ans.dat[1][n * 9 - 8]);
}

猜你喜欢

转载自blog.csdn.net/LPA20020220/article/details/84288049