题意:用1 X 2的矩形填充4 X n的矩形,共有多少种不同方法。
思路:原来写过一个2*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];
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <vector>
#define INF 0x3f3f3f3f
using namespace std;
int a[4], n, m;
typedef long long LL;
struct data{
LL mat[4][4];
};
data mul(data a, data b)
{
data res;
memset(res.mat, 0, sizeof(res.mat));
for(int i = 0; i < 4; i++)
for(int j = 0; j < 4; j++)
for(int i2 = 0; i2 < 4; i2++)
res.mat[i][j] = ((res.mat[i][j]+(a.mat[i][i2]*b.mat[i2][j])%m)%m+m)%m;
return res;
}
int main()
{
a[0] = 1, a[1] = 1, a[2] = 5, a[3] = 11;
while(~scanf("%d %d", &n, &m) && n + m) {
if(n < 4) {
printf("%d\n", a[n] % m);
continue;
}
n -= 3;
data base, res;
memset(base.mat, 0, sizeof(base.mat));
memset(res.mat, 0, sizeof(res.mat));
for(int i = 0; i < 4; i++)
base.mat[i][i] = 1;
res.mat[0][0] = 1, res.mat[0][1] = 5;
res.mat[0][2] = 1, res.mat[0][3] = -1;
res.mat[1][0] = 1, res.mat[2][1] = 1;
res.mat[3][2] = 1;
while(n) {
if(n % 2)
base = mul(res, base);
res = mul(res, res);
n >>= 1;
}
LL res2 = 0;
for(int i = 0; i < 4; i++)
res2 = (res2 + (base.mat[0][i] * a[3 - i])%m)%m;
printf("%lld\n", res2);
}
return 0;
}
京公网安备 11010502036488号