POJ3734 Blocks(矩阵快速幂)

题目链接:http://poj.org/problem?id=3734


Blocks
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 4275   Accepted: 1923

Description

Panda has received an assignment of painting a line of blocks. Since Panda is such an intelligent boy, he starts to think of a math problem of painting. Suppose there are N blocks in a line and each block can be paint red, blue, green or yellow. For some myterious reasons, Panda want both the number of red blocks and green blocks to be even numbers. Under such conditions, Panda wants to know the number of different ways to paint these blocks.

Input

The first line of the input contains an integer T(1≤T≤100), the number of test cases. Each of the next T lines contains an integer N(1≤N≤10^9) indicating the number of blocks.

Output

For each test cases, output the number of ways to paint the blocks in a single line. Since the answer may be quite large, you have to module it by 10007.

Sample Input

2
1
2

Sample Output

2
6

题意:给出n个排成一列的方块,用红、蓝、绿、黄四种颜色给它们染色,要求出染成红色的方块个数和染成绿色的方块个数同时为偶数的染色方案的个数模10007的值为多少。


从左边开始考虑,染第i个格子的时候有三种情况:

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

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

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


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

Ai=2*Ai-1+Bi-1

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

Ci=Bi-1+2*Ci-1

递推式可以写成一个矩阵:

Ai+1      2 1 0   Ai

Bi+1 =  2 2 2   Bi

Ci+1      0 1 2  Ci


因此可以用矩阵快速幂来快速求出答案。


(矩阵快速幂传递矩阵的时候编译总会出现各种奇怪的错误,所以把矩阵乘法直接写进了快速幂中。)


#include 
#include 
#include 
#include 
using namespace std;

#define mod 10007;

int x[5][5],res[5][5];
int n;

void Qmod(int b)
{
	memset(res,0,sizeof(res));
	for (int i=0;i<3;i++) res[i][i]=1;
	while (b)
	{
		if (b&1)
		{
			int tem[5][5];                  //矩阵乘法部分
			for (int i=0;i<3;i++)
			{
				for (int j=0;j<3;j++)
				{
					tem[i][j]=0;
					for (int k=0;k<3;k++)
					{
						tem[i][j]+=res[i][k]*x[k][j];
						tem[i][j]%=mod;
					}
				}
			}
			for (int i=0;i<3;i++)
				for (int j=0;j<3;j++) res[i][j]=tem[i][j];
		}
		int tem[5][5];       //矩阵乘法部分
		for (int i=0;i<3;i++)
		{
			for (int j=0;j<3;j++)
			{
				tem[i][j]=0;
				for (int k=0;k<3;k++)
				{
					tem[i][j]+=x[i][k]*x[k][j];
					tem[i][j]%=mod;
				}
			}
		}
		for (int i=0;i<3;i++)
			for (int j=0;j<3;j++) x[i][j]=tem[i][j];
		b>>=1;
	}
}

int main()
{
	int T;
	scanf("%d",&T);
	while (T--)
	{
		x[0][0]=2;x[0][1]=1;x[0][2]=0;
		x[1][0]=2;x[1][1]=2;x[1][2]=2;
		x[2][0]=0;x[2][1]=1;x[2][2]=2;
		scanf("%d",&n);
		Qmod(n);
		printf("%d\n",res[0][0]);//Ai即为满足条件的情况,是最上方的0,0位置
	}
	return 0;
}


你可能感兴趣的:(动态规划)