题意:
用四中颜色的漆料去粉刷N盒子,求使红色和绿色盒子数量为偶数的方案的个数。
矩阵快速幂:
构造矩阵
2 1 1 0
1 2 0 1
1 0 2 1
0 1 1 2
矩阵的构造原理:
已知红色和绿色为偶数
第一个数为red、green均为偶数的种数
第二个数为red为奇数,green为偶数的种数
第三个数为green为奇数、red为偶数的种数
第四个数为red、green均为奇数的种数
矩阵转移分析 N-1 -> N
(1,1)(1,1)*2(添加yellow或者blue都可以继续保持均为偶数);
(1,2)*1(red为奇数,再添加一个red,得到均为偶数);
(1,3)*1(green为奇数,再添加一个green,得到均为偶数)
(1,4)*0(无论如何一个状态内无法得到两个均为偶数)。
将所有情况加和就得到了,N状态下,两个均为偶数的数量了。
其他位置情况分析类同。
方法分析来自@vici,大神。
/*************************************************************************
> File Name: poj3734.cpp
> Author: cy
> Mail: 1002@qq.com
> Created Time: 2014/8/18 17:40:08
************************************************************************/
#include<iostream>
#include<cstring>
#include <algorithm>
#include<cstdlib>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<iomanip>
#include<list>
#include<deque>
#include<map>
#include <stdio.h>
#include <queue>
#define maxn 50000+5
#define inf 0x3f3f3f3f
#define INF 0x3FFFFFFFFFFFFFFFLL
#define rep(i,n) for(i=0;i<n;i++)
#define reP(i,n) for(i=1;i<=n;i++)
#define ull unsigned long long
#define ll long long
#define cle(a) memset(a,0,sizeof(a))
#define mod 10007
using namespace std;
struct node
{
int num[5][5];
void init(){
cle(num);
}
};
node cal(node a,node b){
int i,j,k;
node c;
c.init();
rep(i,4){
rep(j,4){
rep(k,4){
c.num[i][j]+=a.num[i][k]*b.num[k][j];
c.num[i][j]%=mod;
}
}
}
return c;
}
node mul(node a,int k)
{
if(k==1)return a;
if(k%2==1)return cal(mul(a,k-1),a);
else
{
node temp=mul(a,k/2);
return cal(temp,temp);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
int T;
scanf("%d",&T);
int n;
node val;
int i,j;
int num[16]={2,1,1,0,1,2,0,1,1,0,2,1,0,1,1,2};
rep(i,4)rep(j,4)val.num[i][j]=num[i*4+j];
while(T--)
{
scanf("%d",&n);
node ans=val;
if(n==1)
{
cout<<2<<endl;continue;
}
ans=mul(val,n);
printf("%d\n",ans.num[0][0]%mod);
}
return 0;
}
> File Name: poj3734.cpp
> Author: cy
> Mail: 1002@qq.com
> Created Time: 2014/8/18 17:40:08
************************************************************************/
#include<iostream>
#include<cstring>
#include <algorithm>
#include<cstdlib>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<iomanip>
#include<list>
#include<deque>
#include<map>
#include <stdio.h>
#include <queue>
#define maxn 50000+5
#define inf 0x3f3f3f3f
#define INF 0x3FFFFFFFFFFFFFFFLL
#define rep(i,n) for(i=0;i<n;i++)
#define reP(i,n) for(i=1;i<=n;i++)
#define ull unsigned long long
#define ll long long
#define cle(a) memset(a,0,sizeof(a))
#define mod 10007
using namespace std;
struct node
{
int num[5][5];
void init(){
cle(num);
}
};
node cal(node a,node b){
int i,j,k;
node c;
c.init();
rep(i,4){
rep(j,4){
rep(k,4){
c.num[i][j]+=a.num[i][k]*b.num[k][j];
c.num[i][j]%=mod;
}
}
}
return c;
}
node mul(node a,int k)
{
if(k==1)return a;
if(k%2==1)return cal(mul(a,k-1),a);
else
{
node temp=mul(a,k/2);
return cal(temp,temp);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
int T;
scanf("%d",&T);
int n;
node val;
int i,j;
int num[16]={2,1,1,0,1,2,0,1,1,0,2,1,0,1,1,2};
rep(i,4)rep(j,4)val.num[i][j]=num[i*4+j];
while(T--)
{
scanf("%d",&n);
node ans=val;
if(n==1)
{
cout<<2<<endl;continue;
}
ans=mul(val,n);
printf("%d\n",ans.num[0][0]%mod);
}
return 0;
}