POJ 3734_Blocks

题意:

用红绿蓝黄四种颜色对一序列n个方块涂色,求出绿和红色方块数同时为偶数的染色方案数。mod=10007

分析:

dp+矩阵快速幂
首先明确有三种状态:

  • 红和绿均为偶数
  • 红和绿只有一个为奇数
  • 红和绿均为奇数

设前三种方案数分别为aibici,则可以得到以下递推式:

ai+1=2ai+bibi+1=2ai+2bi+2cici+1=2ci

再利用矩阵快速幂求解即可。

代码:

 #include<cstdio>
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int mod = 10007;
const int N=3;
struct Matrix
{
    int row,cal;
    ll m[N][N];
    Matrix()
    {
        row=3, cal=3;
        m[0][0]=2, m[0][1]=1, m[0][2]=0;
        m[1][0]=2, m[1][1]=2, m[1][2]=2;
        m[2][0]=0, m[2][1]=1, m[2][2]=2;

    }
};
Matrix init(Matrix a, ll t)
{
    for(int i = 0; i < a.row; i++)
        for(int j = 0; j < a.cal; j++)
            a.m[i][j] = t;
    return a;
}
Matrix mul(Matrix a,Matrix b)
{
    Matrix ans;
    ans.row = a.row, ans.cal = b.cal;
    ans = init(ans,0);
    for(int i = 0; i < a.row; i++)
        for(int j = 0; j < b.cal; j++)
            for(int k = 0; k < a.cal; k++)
                ans.m[i][j] = (ans.m[i][j] + a.m[i][k] * b.m[k][j])%mod;
    return ans;
}
ll quick_pow(ll n)
{
    Matrix ans, t;
    ans.row=1, ans.cal=3;
    ans.m[0][0]=1, ans.m[0][1] = 0, ans.m[0][2]=0;
    while(n)
    {
        if(n&1) ans = mul(ans, t);
        t = mul(t, t);
        n>>=1;
    }
    return ans.m[0][0];
}
int main (void)
{
    int T;scanf("%d",&T);
    int n;
    while(T--){
        scanf("%d",&n);
        printf("%d
",quick_pow(n));
    }
    return 0;
} 
原文地址:https://www.cnblogs.com/Tuesdayzz/p/5758786.html