[ZJOI2005]沼泽鳄鱼

Description

BZOJ1898

Luogu2579

Solution

K那么大肯定是矩阵快速幂了。转移矩阵就是邻接矩阵,食人鱼只有2,3,4,显然是有以12为周期的循环的,然后就一起矩乘就好了。

Code

const int N = 55;
const int mod = 10000;

int n, m, St, Ed, K, tmp[15];
struct Matrix {
    int s[N][N];
    void clear() { memset(s, 0, sizeof s); }
    void init() {
        clear();
        for (int i = 1; i <= n; ++i) s[i][i] = 1;
    }
    int* operator[](int x) { return s[x]; }
} S, T[15];
Matrix operator*(Matrix& x, Matrix& y) {
    Matrix ret;
    ret.clear();
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            for (int k = 1; k <= n; ++k) {
                ret[i][j] = (ret[i][j] + x[i][k] * y[k][j]) % mod;
            }
        }
    }
    return ret;
}
Matrix pow_mod(Matrix x, int p) {
    Matrix ret;
    ret.init();
    for (; p; p >>= 1, x = x * x) {
        if (p & 1) ret = ret * x;
    }
    return ret;
}
void main() {
    n = read(), m = read(), St = read() + 1, Ed = read() + 1, K = read();
    S.clear();
    for (int i = 1, x, y; i <= m; ++i) {
        x = read() + 1, y = read() + 1;
        S[x][y] = S[y][x] = 1;
    }
    for (int i = 1; i <= 12; ++i) T[i] = S;
    int nf = read();
    while (nf--) {
        int t = read();
        for (int i = 0; i < t; ++i) tmp[i] = read() + 1;
        for (int j = 1; j <= n; ++j)
            for (int i = 1; i <= 12; ++i) T[i][j][tmp[i % t]] = 0;
    }
    S.init();
    for (int i = 1; i <= 12; ++i) S = S * T[i];
    S = pow_mod(S, K / 12);
    for (int i = 1; i <= K % 12; ++i) S = S * T[i];
    printf("%d
", S[St][Ed]);
}
原文地址:https://www.cnblogs.com/wyxwyx/p/bzoj1898.html