POJ 3734(递推+矩阵快速幂)

题意:你有一排砖,你想给这一排砖中的每一块涂上红,蓝,绿,黄中4种颜色中的其中1种,也就是说每一块砖只能涂1种颜色.现在一排有N块砖,问你有多少种方案,让红色和绿色的砖的块数为偶数.
思路:
从左边开始考虑,染第i+1个格子的时候有三种情况:

  1. 之前i个方块中,红色的方块个数和绿色的方块个数均为偶数,这时想要满足条件,就要染蓝色或黄色;

  2. 之前i个方块中,红色的方块个数和绿色的方块个数中有一个为奇数,这时想满足条件就要染奇数个对应的颜色;

  3. 之前i个方块中,红色的方块个数和绿色的方块个数均不是偶数,这时无法满足条件。

记第一种情况为A,第二种情况为B,第三种情况为C,则可以得出以下递推式:

Ai=2*Ai-1+Bi-1

Bi=2Ai-1+2Bi-1+2*Ci-1

Ci=Bi-1+2*Ci-1
POJ 3734(递推+矩阵快速幂)_第1张图片
这道题核心在于递推,剩下的就是矩阵快速幂的模板

#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
struct mat{
	ll a[5][5];
};
int mod=10007,n,k;
mat operator*(mat x,mat y)
{
	mat ans;
	memset(ans.a,0,sizeof(ans.a));
	for(int i=0;i<3;i++)
		for(int j=0;j<3;j++)
			for(int k=0;k<3;k++)
			{
				ans.a[i][j]+=(ll)x.a[i][k]*y.a[k][j];
				ans.a[i][j]%=mod;
			}
	return ans;
}
mat qmod(mat a,int k)
{
	mat ret;
	memset(ret.a,0,sizeof(ret.a));
	for(int i=0;i<3;i++)
        ret.a[i][i]=1;
    while(k)
    {
        if(k&1)
        {
            ret= ret*a;
        }
        k>>=1;
        a=a*a;
    }
    return ret;
}
int main()
{
	int t;
	cin>>t;
	while(t--)
    {
        cin>>n;
        if(n==0) cout<<"1"<<endl;
        else
        {
            mat base;
            base.a[0][0] = 2; base.a[0][1]  = 1; base.a[0][2] = 0;
            base.a[1][0] = 2; base.a[1][1]  = 2; base.a[1][2] = 2;
            base.a[2][0] = 0; base.a[2][1]  = 1; base.a[2][2] = 2;
            mat ans = qmod(base, n);
            printf("%d\n", ans.a[0][0]);
        }
    }
}

你可能感兴趣的:(POJ 3734(递推+矩阵快速幂))