POJ - 3734 -- Blocks

题目来源:http://poj.org/problem?id=3734

用a[i]表示前i块红色与绿色全为奇数的方案数。b[i]表示前i块红色与绿色全为偶数的方案数。c[i]表示前i块红色与绿色的块数一奇一偶的方案数。

因此转移方程可以表示为:

a[i]=2*a[i-1]+0*b[i-1]+1*c[i-1]

b[i]=0*a[i-1]+2*b[i-1]+1*c[i-1]

c[i]=2*a[i-1]+2*b[i-1]+2*c[i-1]

因此矩阵可以构造出,所要求的即为b[n]的值。

代码:

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
const ll mod=10007;
const int N=3;
int n;
struct matrix {
    ll num[10][10];

    matrix() { memset(num, 0, sizeof(num)); }

    matrix operator*(const matrix &x) {
        matrix c;
        for (int i = 1; i <= N; ++i)
            for (int j = 1; j <= N; ++j)
                for (int k = 1; k <= N; ++k)
                    c.num[i][j] = (c.num[i][j] + num[i][k] * x.num[k][j]) % mod;
        return c;
    }

    matrix &operator=(const matrix &x) {
        for (int i = 1; i <= N; ++i)
            for (int j = 1; j <= N; ++j)
                num[i][j] = x.num[i][j];
        return *this;
    }
};
int table[4][4]={{0,0,0,0},{0,2,0,1},{0,0,2,1},{0,2,2,2}};
matrix pow_mod(matrix& x,int k) {
    matrix ans;
    for (int i = 1; i <= N; ++i)ans.num[i][i] = 1;
    while (k) {
        if (k & 1)ans = ans * x;
        x = x * x;
        k >>= 1;
    }
    return ans;
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int _;
    cin >> _;
    while (_--) {
        cin >> n;
        matrix ans;
        for (int i = 1; i <= N; ++i) {
            for (int j = 1; j <= N; ++j)
                ans.num[i][j] = table[i][j];
        }
        ans = pow_mod(ans, n - 1);
        ll tot = (ans.num[2][2] * 2 + ans.num[2][3] * 2) % mod;
        cout << tot << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/moon_sky1999/article/details/81296866