题意是给4种不同颜色的转头n个,问红、蓝2种颜色为偶数的种树有几种。
可以明显得知是递推,
设an为红绿为偶数的个数
bn为红绿之间只有一个为偶数的个数
cn为红绿均为奇数的个|数
那么得到递推式an=(an-1)*2+bn-1
bn=(bn-1)*2+(an-1)*2
cn=(an-1)*2+(bn1)*2+(cn-1)*2
那么可以得到这么个矩阵
an=|2 1 0|*|an-1|
bn=|2 2 0|*|bn-1|
cn=|2 2 2|*|cn-1|
然后注意如果an-1变成了1,这个矩阵的次方应该是n-1次。
但是对于这题是求an,那么可以乘n次后,这个矩阵变成an+1,其中的第一行第一列就代表an=(an+1)-1
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
const int MOD=1e4+7;
struct ttt{
int map1[5][5];
};
int n;
ttt mul(ttt &a,ttt &b){ //矩阵A*B
ttt c;
int i,j,k;
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
c.map1[i][j]=0;
for(k=1;k<=n;k++){
c.map1[i][j]+=a.map1[i][k]*b.map1[k][j];
c.map1[i][j]%=MOD;
}
}
}
return c;
}
ttt mul_self(ttt &a){
ttt b;
int i,j,k;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
b.map1[i][j]=0;
for(k=1;k<=n;k++){
b.map1[i][j]+=a.map1[i][k]*a.map1[k][j];
b.map1[i][j]%=MOD;
}
}
return b;
}
ttt pow1(ttt &a,int k){
ttt b;
int i,j;
memset(b.map1,0,sizeof(b.map1));
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i==j)
b.map1[i][j]=1;
while(k){
//cout << "k=" <<k <<endl;
if(k&1)
b=mul(b,a);
k=k>>1;
a=mul_self(a);
}
return b;
}
int main(){
//freopen("in.txt","r",stdin);
int i,j,k,l,f1,f2,f3,t1,t2,t3;
int r,c,m;
int a1,b1,c1;
int T;
cin >>T;
while(T--){
cin >> m;
ttt a;
memset(a.map1,0,sizeof(a.map1));
n=3;
a.map1[1][1]=2;
a.map1[1][2]=1;
a.map1[1][3]=0;
a.map1[2][1]=2;
a.map1[2][2]=2;
a.map1[2][3]=2;
a.map1[3][1]=0;
a.map1[3][2]=1;
a.map1[3][3]=2;
a=pow1(a,m);
/*for(i=1;i<=3;i++){
for(j=1;j<=3;j++)
cout << a.map1[i][j] << " ";
cout <<endl;
}*/
cout << a.map1[1][1] << endl;
}
return 0;
}