Tired of the Tri Tiling game finally, Michael turns to a more challengeable game, Quad Tiling:
In how many ways can you tile a 4 × N (1 ≤ N ≤ 109) rectangle with 2 × 1 dominoes? For the answer would be very big, output the answer modulo M (0 < M ≤ 105).
Input
Input consists of several test cases followed by a line containing double 0. Each test case consists of two integers, N and M, respectively.
Output
For each test case, output the answer modules M.
Sample Input
1 10000
3 10000
5 10000
0 0
Sample Output
1
11
95
由Tri Tiling引申出来的题目,问在4*n的长方形中摆放1*2的方块的方案数,很明显的递推题,在纸上大概画一画就能把几种情形推出来,得到公式f[n]=f[n-1]+4f[n-2]+2(f[n-3]+f[n-4]+f[n-5]+…..+f[0])+3(f[n-6]+f[n-8]+…..),首先因为n的大小太大了,想这样递推数组都存不下,时间也不够,就应该用矩阵快速幂计算,而如果想用矩阵快速幂的话这个公式是不满足的,因为矩阵大小不固定,然而当我们将f[n]-f[n-2]之后,就会得到f[n]=f[n-1]+5f[n-2]+f[n-3]-f[n-4],就能得到快速幂的矩阵,套入计算就行。因为矩阵里有负数,计算一个位置的结果时,前面的正数取模变小了,后面的负数没达到模数那么大,结果相加就变成负数了。所以矩阵相乘时注意要+mod)%mod。
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
#include<vector>
#include<string>
#include<cmath>
#include<set>
#include<map>
#include<queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
//const int mod = 1000000007;
const int maxm = 1000010;
const int maxn = 1000000005;
int n;
int m;
struct ju{
ll a[4][4];
ju(){}
ju(ll *num){
int cnt = 0;
for (int i = 0; i < 4; i++){
for (int j = 0; j < 4; j++){
a[i][j] = num[cnt++];
}
}
}
ju operator *(const ju & tmp){
ju ans;
memset(ans.a, 0, sizeof(ans.a));
for (int i = 0; i<4; i++){
for (int j = 0; j<4; j++){
for (int k = 0; k<4; k++){
ans.a[i][j] = ((ans.a[i][j] +( a[i][k] * tmp.a[k][j])%m)+m) % m;
}
}
}
return ans;
}
};
int pow_mod(int b){
ll num[16] = { 1, 5, 1, -1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0 };
ll nu[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
ju a(num);
ju c(nu);
while (b){
if (b % 2)c = c*a;
a = a*a;
b /= 2;
}
int ans = 0;
ans = (ans + c.a[0][0] * 11) % m;
ans = (ans + c.a[0][1] * 5) % m;
ans = (ans + c.a[0][2] * 1) % m;
ans = (ans + c.a[0][3]) % m;
return ans;
}
//1 1 5 11
int f[4] = { 1, 1, 5, 11 };
int main() {
while (scanf("%d%d", &n, &m), m + n){
if (n < 4){
printf("%d\n", f[n] % m);
}
else{
printf("%d\n", pow_mod(n - 3));
}
}
return 0;
}