poj 3734 矩阵快速幂、母函数

题意:
         用四中颜色的漆料去粉刷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: [email protected]
    > Created Time: 2014/8/18 17:40:08
************************************************************************/

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define maxn 50000+5

#define inf 0x3f3f3f3f
  #define INF 0x3FFFFFFFFFFFFFFFLL
#define rep(i,n) for(i=0;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<           }
          ans=mul(val,n);
          printf("%d\n",ans.num[0][0]%mod);
     }
    return 0;
}

你可能感兴趣的:(矩阵快速幂)