poj 3420 Quad Tiling

http://poj.org/problem?id=3420

  继续矩阵快速幂!

  题目意思是给你一个4*n的矩阵用1*2的砖块填充,问有多少种填充的方法。这题可以模仿一道老题(2*n的矩阵用1*2的砖块填充)的递推方法。不过如果是这样递推,推着推着会发现,递推式会有无穷多个项。不过从第三项开始,每项乘以的系数有规律,具体的规律还是查看代码吧!这题我找到的递推式中要分奇偶项,所以构建矩阵的时候就要划分奇偶情况来讨论,所以就构建出奇偶两种矩阵来。奇矩阵是在求奇数项的时候用的,偶矩阵同理。

此题轻松1y,代码如下:

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 
  5 using namespace std;
  6 const int maxSize = 5;
  7 const int initMod = 1E9 + 7;
  8 const int Odd[5][5] = { {1, 1, 0, 0, 0},
  9                          {4, 0, 1, 0, 0},
 10                          {3, 0, 1, 0, 0},
 11                          {2, 0, 0, 1, 0},
 12                          {2, 0, 0, 0, 1} };
 13 const int Even[5][5] = { {1, 1, 0, 0, 0},
 14                           {4, 0, 0, 1, 0},
 15                           {2, 0, 1, 0, 0},
 16                           {3, 0, 0, 1, 0},
 17                           {3, 0, 0, 0, 1}};
 18 
 19 int curSize = maxSize;
 20 int curMod = initMod;
 21 
 22 struct Matrix {
 23     int val[maxSize][maxSize];
 24 
 25     Matrix (bool ONE = false) {
 26         for (int i = 0; i < curSize; i++) {
 27             for (int j = 0; j < curSize; j++) {
 28                 val[i][j] = 0;
 29             }
 30             if (ONE) val[i][i] = 1;
 31         }
 32     }
 33 
 34     void print(int _l = maxSize, int _w = maxSize) {
 35         for (int i = 0; i < _l; i++) {
 36             for (int j = 0; j < _w; j++) {
 37                 if (j) putchar(' ');
 38                 printf("%d", val[i][j]);
 39             }
 40             puts("");
 41         }
 42     }
 43 } odd, even, Base;
 44 
 45 Matrix operator * (Matrix &_a, Matrix &_b) {
 46     Matrix ret = Matrix();
 47 
 48     for (int i = 0; i < curSize; i++) {
 49         for (int k = 0; k < curSize; k++) {
 50             if (_a.val[i][k]) {
 51                 for (int j = 0; j < curSize; j++) {
 52                     ret.val[i][j] += _a.val[i][k] * _b.val[k][j];
 53                     ret.val[i][j] %= curMod;
 54                 }
 55             }
 56         }
 57     }
 58 
 59     return ret;
 60 }
 61 
 62 Matrix operator ^ (Matrix &_a, int _p) {
 63     Matrix ret = Matrix(true);
 64     Matrix __a = _a;
 65 
 66     while (_p) {
 67         if (_p & 1) ret = ret * __a;
 68         __a = __a * __a;
 69         _p >>= 1;
 70     }
 71 //    puts("yeah!!!");
 72 
 73     return ret;
 74 }
 75 
 76 void initMat() {
 77     odd = Matrix();
 78     even = Matrix();
 79     Base = Matrix();
 80 
 81     for (int i = 0; i < 5; i++) {
 82         for (int j = 0; j < 5; j++) {
 83             even.val[i][j] = Even[i][j];
 84             odd.val[i][j] = Odd[i][j];
 85         }
 86     }
 87     Base.val[0][0] = 5;
 88     Base.val[0][1] = 1;
 89     Base.val[0][4] = 1;
 90 //
 91 //    puts("odd");
 92 //    odd.print();
 93 //    puts("even");
 94 //    even.print();
 95 }
 96 
 97 int deal(int n) {
 98     Matrix ans = Base;
 99     Matrix TWO = odd * even;
100 
101     if (n == 1) return 1 % curMod;
102     if (n == 2) return 5 % curMod;
103 //    puts("~~TWO");
104 //    TWO.print();
105     ans = TWO ^ ((n >> 1) - 1);
106     ans = Base * ans;
107     if (n & 1) ans = ans * odd;
108 //    puts("~ans");
109 //    ans.print();
110 
111     return ans.val[0][0];
112 }
113 
114 int main() {
115     int n;
116 
117       freopen("in", "r", stdin);
118     initMat();
119     while (~scanf("%d%d", &n, &curMod) && (n || curMod)) {
120         printf("%d\n", deal(n));
121     }
122 
123     return 0;
124 }

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/poj_3420_Lyon.html