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 <iostream>
#include <cstdio>
#include <cstring>
#include <string>
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;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值