1. 程式人生 > >[Luogu P4159] [BZOJ 1297] [SCOI2009]迷路

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

洛谷傳送門

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