Quad Tiling POJ

来源:互联网 发布:sql可以装在d盘吗 编辑:程序博客网 时间:2024/05/01 22:55

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 11int 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;}
0 0
原创粉丝点击