方格填色 - 牛客

ps:想到了要用矩阵递推,就是没找到式子。dp [ i ][ s ] : 第 i 列状态为 s 的方案数(为了方便用位运算,1表示白色,0表示黑色),剩下的找那个表达矩阵,只要状态 s1 & s2 = 0,则 s1 可以转移到 s2。

const int mod = 1000000007;

struct mat {
    LL t;
    LL A[32][32];
    void Inite(LL n) {
        t = n;
        mem(A, 0);
    }
    mat operator * (const mat tp) {
        mat ans;
        ans.Inite(t);
        rep(i, 0, t) rep(j, 0, t) rep(k, 0, t) {

            ans.A[i][j] += A[i][k] * tp.A[k][j];
            ans.A[i][j] %= mod;
        }
        return ans;
    }
    void operator = (const mat tp) {
        rep(i, 0, t) rep(j, 0, t) A[i][j] = tp.A[i][j];
    }
};

LL n, m;

mat qpow(mat C, LL x) {
    mat B;
    B.Inite((1 << m));
    rep(i, 0, (1 << m)) B.A[i][i] = 1;
    for (; x; C = C * C, x >>= 1) {
        if (x & 1) B = B * C;
    }
    return B;
}

int main()
{
    cin >> m >> n;
    mat res;
    res.Inite((1 << m));
    for (int i = 0; i < (1 << m); ++i) {
        for (int j = 0; j < (1 << m); ++j) {
            if (!i && !j) continue;
            if (!(i & j)) res.A[i][j] = 1;
        }
    }

    res = qpow(res, n - 1);

    LL ans = 0;
    rep(i, 0, (1 << m)) rep(j, 0, (1 << m)) ans = (ans + res.A[i][j]) % mod;
    cout << ans << endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zgglj-com/p/9653154.html