【dp+数论】PKU-3420-Quad Tiling

来源:互联网 发布:淘宝运营教程视频下载 编辑:程序博客网 时间:2024/06/05 14:35

题目要求用2x1的小长方形去填满一个4xN的大长方形,问有多少种填法……如果数据不大,那完全就是一道很裸的状态压缩dp,不过这题数据大得惊人,所以就想到了矩阵的快速幂相乘,不过找相邻之间的关系那里还是挺麻烦的,这里就贴上以为牛人关于用一个dfs来找关系的解析点击打开链接。

题目

#include<iostream>#include<cstdio>#include<cstring>#include<map>using namespace std;#define LL long long#define N (1<<4)int mod;struct matrix{    int mat[N][N];}tmp,ans;void dfs(int d,int now,int pre)               //d表示第几列{    if(d>4)return;    if(d==4)    {        tmp.mat[pre][now]++;               //表示由第i-1行状态pre转移到第i行状态now的方法数        return;    }    dfs(d+1,now<<1,(pre<<1)|1);               //i行不放,但i-1行应该是是有的    dfs(d+1,(now<<1)|1,pre<<1);               //竖直放置,第i行增加一个状态,而第i-1行本应该就是空的,好让能放下去    dfs(d+2,(now<<2)|3,(pre<<2)|3);               //横放在第i行,这时i-1行应该是满的,要不就会留空了}matrix mul(matrix a,matrix b){    matrix ant;    for(int i=0;i<N;i++)    {        for(int j=0;j<N;j++)        {            ant.mat[i][j]=0;            for(int k=0;k<N;k++)            {                (ant.mat[i][j]+=a.mat[i][k]*b.mat[k][j])%=mod;            }        }    }    return ant;}void pow(int n,matrix Mat){    while(n)    {        if(n&1)ans=mul(ans,Mat);        Mat=mul(Mat,Mat);        n>>=1;    }}int main(){    freopen("a.txt","r",stdin);    memset(tmp.mat,0,sizeof(tmp.mat));    dfs(0,0,0);               //找相邻之间状态转移的关系    int n;    while(scanf("%d%d",&n,&mod)&&n)    {        ans=tmp;        pow(n,tmp);        printf("%d\n",ans.mat[0][N-1]);    }    return 0;}


原创粉丝点击