poj3420 棋盘覆盖

Quad Tiling
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 3422   Accepted: 1492

Description

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

前序分析见我的另一篇博客,传送门:poj2411题解 

这题其实采用的是poj2411的第二种方法,但是利用第二种方法,我们发现行数太多,必然超时。

但是我们观察poj2411每重for做了一件什么事?

对于m列,我们有1<<m个状态,状态之间有转移关系,我们将这些状态看成点,那么这些点之间的关系看成距离为1的路径,那么每重for其实是在原先到达情况下,又多走了距离1,也就是相当于做了k重for表示距离小于等于k的路径条数,这个正好是可达矩阵的k次方,突然吓傻,矩阵快速幂搞起啊!

最后,因为第0行我们假设是全1状态这样可以保证不影响第一行的方法,而最终状态也是全1,也就是本题转化为从点15走到点15,距离小于等于n的路径条数。

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#define Maxn 20
using namespace std;

int mod;
int d;
struct matrix{
    long long mat[Maxn][Maxn];
    matrix(){memset(mat,0,sizeof mat);}
    matrix operator*(matrix &x){
        matrix ans;
        for(int i=0;i<d;i++)
            for(int j=0;j<d;j++)
                for(int k=0;k<d;k++){
                    ans.mat[i][j]+=mat[i][k]*x.mat[k][j];
                    ans.mat[i][j]%=mod;
                }
        return ans;
    }
}x;
matrix quick_pow(matrix x,int k){
    matrix ans;
    for(int i=0;i<d;i++)
        ans.mat[i][i]=1;
    while(k){
        if(k&1) ans=ans*x;
        x=x*x;
        k>>=1;
    }
    return ans;
}
int n,m;
void dfs(int c,int s,int scur){
    if(c>4) return;
    if(c==4){
        x.mat[s][scur]=1;
        return;
    }
    dfs(c+1,s<<1,scur<<1|1);
    dfs(c+1,s<<1|1,scur<<1);
    dfs(c+2,s<<2|3,scur<<2|3);
}
int main()
{
    while(cin>>n>>mod,n){
        memset(x.mat,0,sizeof x.mat);
        dfs(0,0,0);
        d=16;
        x=quick_pow(x,n);
        cout<<x.mat[15][15]<<endl;
    }
	return 0;
}

你可能感兴趣的:(poj3420 棋盘覆盖)