poj 3734 Blocks

从左边开始染色,到第$i$个方块为止,红绿都是偶数的方案数为$a_i$,红绿恰有一个是偶数的方案为$b_i$,红绿都是奇数的方案为$c_i$,从而有如下状态转移方程:

$a_{i+1} = 2 \times a_i + b_i$

$b_{i+1} = 2 \times  a_i + 2 \times b_i + 2 \times c_i$

$c_{i+1} = b_i + 2 \times c_i$

从而可以用矩阵表示:

\begin{equation} \left( \begin{array}{c} a_i \\ b_i \\ c_i \end{array} \right) = \left( \begin{array}{ccc} 2 & 1 & 0 \\ 2 & 2 & 2 \\ 0 & 1 & 2 \end{array} \right)^i \left( \begin{array}{c} 1\\ 0\\ 0\\ \end{array} \right)  \end{equation}

 最终使用矩阵的快速幂即可求解。

 1 #define     MOD 10007
 2 #define     M 3
 3 #include  <cstdio>
 4 #include  <cstdlib>
 5 #include  <iostream>
 6 #include  <cstring>
 7 int N;
 8 using namespace std;
 9 class Matrix
10 {
11     public:
12         int a[M][M];
13         Matrix(bool init = 0)
14         {
15             memset(a, 0, sizeof(a));
16             if( init == 1 )
17             {
18                 for( int i = 0 ; i < M ; i++ )
19                 {
20                     a[i][i] = 1;
21                 }
22             }
23         }
24         int * operator [](int i)
25         {
26             return a[i];
27         }
28         const int * operator [](int i)const
29         {
30             return a[i];
31         }
32 };
33 Matrix A;
34 void add(int &a, int b)
35 {
36     a += b;
37     while( a >= MOD )
38     {
39         a -= MOD;
40     }
41 }
42 Matrix operator * (const Matrix &a, const Matrix &b)
43 {
44     Matrix c;
45     for( int i = 0 ; i < M ; i++ )
46     {
47         for( int j = 0 ; j < M ; j++ )
48         {
49             for( int k = 0 ; k < M ; k++ )
50             {
51                 add(c[i][k], 1ll * a[i][j] * b[j][k] %MOD);
52             }
53         }
54     }
55     return c;
56 }
57 Matrix quick_pow(Matrix m, int n)
58 {
59     Matrix ans(1);
60     while( n )
61     {
62         if( n & 1 )
63         {
64             ans = ans * m;
65         }
66         n = n>>1;
67         m = m * m;
68     }
69     return ans;
70 }
71 void solve()
72 {
73     Matrix ans;
74     ans = quick_pow(A, N);
75     printf ( "%d\n", ans[0][0]);
76 }
77 int main(int argc, char *argv[])
78 {
79     int T;
80     scanf ( "%d", &T );
81     A[0][0] = 2, A[0][1] = 1;
82     A[1][0] = 2, A[1][1] = 2, A[1][2] = 2;
83     A[2][1] = 1, A[2][2] = 2;
84     while( T-- )
85     {
86         scanf ( "%d", &N );
87         solve();
88     }
89 }

 

posted @ 2014-09-29 18:52  jostree  阅读(164)  评论(0编辑  收藏  举报