好吧,我应该不是第一次接触这种思想了,可是我以前做的题目都是显式的给出递推关系。。这样递推关系隐藏的还没有遇见过,也算是长长见识了。
总之要想办法转到矩阵上面来。为了方便称呼,我这里把四种颜色叫做a,b,c,d,而c,d就是题目特定要求的颜色。
然后考虑这三种状态: A(i)=格子数为i 块时c,d个数都是偶数的方法数
B(i)=格子数为i 块时c,d个数恰有一个是奇数的方法数
C(i)=格子数为i 块时c,d个数均为奇数的方法数
定义了这三个状态之后我们就可以开始递推了。
A(i+1)=2*A(i)+B(i)
B(i+1)=2*A(i)+2*B(i)+2*C(i)
C(i+1)=2*C(i)+B(i)
很眼熟是不是?马上发现就是线性代数里面的线性变换,马上上矩阵快速幂,此题就做完了。
#include<cstdio>
#include<cstring>
using namespace std;
const int modulu=10007;
int n,t;
int arr[3][3],muti[3][3],te[3][3];
void mul(int[3][3],int[3][3]);
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
if(n==1)
printf("2\n");
else{
memset(arr,0,sizeof arr);
arr[0][0]=arr[1][1]=arr[2][2]=1;
memset(muti,0, sizeof muti);
muti[0][0]=muti[1][0]=muti[1][1]=muti[1][2]=muti[2][2]=2;
muti[0][1]=muti[2][1]=1;
--n;
while(n){
if(n&1)
mul(arr,muti);
mul(muti,muti);
n>>=1;
}
// for(int i=0;i<3;++i){
// for(int j=0;j<3;++j)
// printf("%d ",arr[i][j]);
// printf("\n");
// }
printf("%d\n",((arr[0][0]+arr[0][1])<<1)%modulu);
}
}
return 0;
}
void mul(int a[3][3],int b[3][3]){
memset(te,0,sizeof te);
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
for(int k=0;k<3;++k)
te[i][j]+=a[i][k]*b[k][j],te[i][j]%=modulu;
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
a[i][j]=te[i][j];
}