题目链接:http://poj.org/problem?id=3420
题意:用1 X 2的矩形填充4 X n的矩形,共有多少种不同方法。
思路:听说有公式,推了一下
如果n-1行填满的话,第n行只有一种情况,如果n-2行填满的话,有4种情况;
如果n-3行填满的话,有2种情况;
如果n-4行填满的话,有3种情况;
如果n-5行填满的话,有2种情况;
如果n-6行填满的话,有3种情况;
...
f[n] = f[n-1] + 4*f[n-2] + 2 * [ f[n-3] + f[n-5] + f[n-7] +.... ] + 3 * [ f[n-4] + f[n-6] + f[n-8] +.... ] ; (1)
f[n - 2] = f[n-3] + 4*f[n-4] + 2 * [ f[n-5] + f[n-7] + f[n-9] +.... ] + 3 * [ f[n-6] + f[n-8] + f[n-10] +.... ] ; (2)
(1) - (2) 化简得 f[n] = f[n-1] + 5f[n-2] + f[n-3] - f[n-4]
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cstdlib> 6 #include <cmath> 7 #include <set> 8 #include <map> 9 #include <queue> 10 #include <vector> 11 #define INF 0x3f3f3f3f 12 using namespace std; 13 int a[4], n, m; 14 typedef long long LL; 15 struct data{ 16 LL mat[4][4]; 17 }; 18 data mul(data a, data b) 19 { 20 data res; 21 memset(res.mat, 0, sizeof(res.mat)); 22 for(int i = 0; i < 4; i++) 23 for(int j = 0; j < 4; j++) 24 for(int i2 = 0; i2 < 4; i2++) 25 res.mat[i][j] = ((res.mat[i][j]+(a.mat[i][i2]*b.mat[i2][j])%m)%m+m)%m; 26 return res; 27 } 28 int main() 29 { 30 a[0] = 1, a[1] = 1, a[2] = 5, a[3] = 11; 31 while(~scanf("%d %d", &n, &m) && n + m) { 32 if(n < 4) { 33 printf("%d ", a[n] % m); 34 continue; 35 } 36 n -= 3; 37 data base, res; 38 memset(base.mat, 0, sizeof(base.mat)); 39 memset(res.mat, 0, sizeof(res.mat)); 40 for(int i = 0; i < 4; i++) 41 base.mat[i][i] = 1; 42 res.mat[0][0] = 1, res.mat[0][1] = 5; 43 res.mat[0][2] = 1, res.mat[0][3] = -1; 44 res.mat[1][0] = 1, res.mat[2][1] = 1; 45 res.mat[3][2] = 1; 46 while(n) { 47 if(n % 2) 48 base = mul(res, base); 49 res = mul(res, res); 50 n >>= 1; 51 } 52 LL res2 = 0; 53 for(int i = 0; i < 4; i++) 54 res2 = (res2 + (base.mat[0][i] * a[3 - i])%m)%m; 55 printf("%lld ", res2); 56 } 57 return 0; 58 }
下面是某个大牛写的代码
1 //某个低调的大牛写的 2 #include <algorithm> 3 #include <iostream> 4 #include <cstdlib> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <vector> 9 #include <ctime> 10 #include <cmath> 11 #include <queue> 12 #include <set> 13 #include <map> 14 using namespace std; 15 #define Fill(x, y) memset((x), (y), sizeof(x)) 16 #define Rep(i, x, y) for(int i = x; i <= y; ++i) 17 #define Dow(i, x, y) for(int i = x; i >= y; --i) 18 typedef long long LL; 19 typedef pair <int, int> P; 20 typedef pair <LL, LL> PLL; 21 const LL inf = 1e18; 22 const int N = 1e5 + 10; 23 int GCD(int a, int b) { 24 return b ? GCD(b, a % b) : a; 25 } 26 int LCM(int a, int b) { 27 return a * b / GCD(a, b); 28 } 29 struct data { 30 LL mat[5][5]; 31 }; 32 33 LL f[N] , mod; 34 35 data operator *(data a, data b) { 36 data res; 37 for(int i = 1 ; i <= 4 ; ++i) { 38 for(int j = 1 ; j <= 4 ; ++j) { 39 res.mat[i][j] = 0; 40 for(int k = 1 ; k <= 4 ; ++k) { 41 res.mat[i][j] = ((a.mat[i][k] * b.mat[k][j] % mod + res.mat[i][j]) % mod + mod) % mod; 42 } 43 } 44 } 45 return res; 46 } 47 48 data operator ^(data a , LL n) { 49 data res; 50 for(int i = 1 ; i <= 4 ; ++i) { 51 for(int j = 1 ; j <= 4 ; ++j) { 52 res.mat[i][j] = (i == j); 53 } 54 } 55 while(n) { 56 if(n & 1) 57 res = res * a; 58 a = a * a; 59 n >>= 1; 60 } 61 return res; 62 } 63 64 int main() 65 { 66 f[1] = 1 , f[2] = 5 , f[3] = 11 , f[4] = 36; 67 LL n; 68 while(cin >> n >> mod && (mod || n)) { 69 if(mod == 1) { 70 cout << 0 << endl; 71 continue; 72 } 73 if(n <= 4) { 74 cout << f[n] % mod << endl; 75 continue; 76 } 77 data a , res; 78 for(int i = 1 ; i <= 4 ; ++i) { 79 for(int j = 1 ; j <= 4 ; ++j) { 80 a.mat[i][j] = 0; 81 res.mat[i][j] = 0; 82 } 83 res.mat[i][1] = f[5 - i] % mod; 84 } 85 a.mat[1][1] = a.mat[2][1] = a.mat[3][2] = a.mat[4][3] = a.mat[1][3] = 1; 86 a.mat[1][2] = 5 , a.mat[1][4] = -1; 87 a = a ^ (n - 4); 88 res = a * res; 89 cout << (res.mat[1][1] + mod) % mod << endl; 90 } 91 return 0; 92 }