POJ 3734_Blocks

来源:互联网 发布:想学电脑编程 编辑:程序博客网 时间:2024/06/04 23:33

题意:

用红绿蓝黄四种颜色对一序列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\n",quick_pow(n));    }    return 0;} 
0 0