题目描述
衣食无忧的 Q老师 有一天突发奇想,想要去感受一下劳动人民的艰苦生活。
具体工作是这样的,有 N 块砖排成一排染色,每一块砖需要涂上红、蓝、绿、黄这 4 种颜色中的其中 1 种。且当这 N 块砖中红色和绿色的块数均为偶数时,染色效果最佳。
为了使工作效率更高,Q老师 想要知道一共有多少种方案可以使染色效果最佳,你能帮帮他吗?
输入格式
第一行为 T,代表数据组数。(1 ≤ T ≤ 100)
接下来 T 行每行包括一个数字 N,代表有 N 块砖。(1 ≤ N ≤ 1e9)
输出格式
输出满足条件的方案数,答案模 10007。
输入样例
2
1
2
输出样例
2
6
思路
对连续的格子进行染色,很明显该问题具有子结构,可使用动态规划的思想,设A[i]为对i个格子染色红绿格子数均为偶数的染色方案。
因为n很大,所以应考虑优化dp的方法,增设状态B[i]为染i个格子红绿均为奇数的方案,C[i]为染i个格子,红绿一奇一偶的方案数。
故可得
A[i]=2*A[i-1]+C[i-1]
B[i]=2*B[i-1]+C[i-1]
C[i]=2*A[i-1]+2*B[i-1]+2*C[i-1]
可利用上式构造矩阵方程,利用矩阵快速幂进行优化。
代码
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
const int N=3;
struct Matrix{
int x[N][N];
Matrix()
{
memset(x,0,sizeof(x));
}
Matrix(Matrix&b)
{
memcpy(x,b.x,sizeof(x));
}
Matrix operator*(Matrix&b)
{
Matrix ret;
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
for(int k=0;k<N;k++)
{
ret.x[i][j]+=x[i][k]*b.x[k][j]%10007;
ret.x[i][j]%=10007;
}
}
}
return ret;
}
};
Matrix quick_pow(Matrix a,int x)
{
Matrix ret;
for(int i=0;i<N;i++)
ret.x[i][i]=1;
while(x)
{
if(x&1)ret=ret*a;
a=a*a;
x>>=1;
}
return ret;
}
int main() {
int T;
scanf("%d",&T);
while(T--)
{
int k;
scanf("%d",&k);
if(k==1)
{
printf("2\n");
continue;
}
Matrix temp;
temp.x[0][0]=2;temp.x[0][2]=1;
temp.x[1][1]=2;temp.x[1][2]=1;
temp.x[2][0]=temp.x[2][1]=temp.x[2][2]=2;
temp=quick_pow(temp,k-1);
int ans=0;
ans+=temp.x[0][0]*2%10007;
ans+=temp.x[0][2]*2%10007;
ans%=10007;
printf("%d\n",ans);
}
return 0;
}