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

题目要求用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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值