列表

详情


NC20281. [SCOI2011]地板

描述

lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西。小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板。现在小L想知道,用L型的地板铺满整个客厅有多少种不同的方案? 
需要注意的是,如下图所示,L型地板的两端长度可以任意变化,但不能长度为0。铺设完成后,客厅里面所有没有柱子的地方都必须铺上地板,但同一个地方不能被铺多次。

输入描述

输入的第一行包含两个整数,R和C,表示客厅的大小。
接着是R行,每行C个字符。’_’表示对应的位置是空的,必须铺地板;’*’表示对应的位置有柱子,不能铺地板。

输出描述

输出一行,包含一个整数,表示铺满整个客厅的方案数。由于这个数可能很大,只需输出它除以20110520的余数。

示例1

输入:

2 2

*_

__

输出:

1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++ 11.0.1) 解法, 执行用时: 115ms, 内存消耗: 5796K, 提交时间: 2022-12-11 15:10:44

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int P=20110520;
ll p4[15];
int a[105][15]={0};
ll bit[2][300000],val[2][300000];
int head[300000],nex[300000];
int tot[300000];
int n,m;
void insert(ll b,ll v,int now)
{
    int tmp=b%299987;
    for(int i=head[tmp];i;i=nex[i])
        if(bit[now][i]==b) {val[now][i]=(val[now][i]+v)%P;return;}
    nex[++tot[now]]=head[tmp];
    head[tmp]=tot[now];
    bit[now][tot[now]]=b;
    val[now][tot[now]]=v%P;
}
void solve(){
    int pre=0,now=1;
    tot[now]=1;
    bit[now][1]=0;
    val[now][1]=1;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=tot[now];j++)
            bit[now][j]<<=2;
        for(int j=1;j<=m;j++){
            memset(head,0,sizeof(head));
            swap(pre,now);
            tot[now]=0;
            for(int k=1;k<=tot[pre];k++)
            {
                ll b=bit[pre][k],v=val[pre][k];
                ll b1=(b>>(2*(j-1)))%4;
                ll b2=(b>>(2*j))%4;
                if(!a[i][j]) {
                    if(!b1&&!b2) insert(b,v,now);  
                    
                }
                else if(b1==1&&b2==1) insert(b-p4[j-1]-p4[j],v,now);
                else if(!b1&&!b2) {
                    if(a[i][j+1]&&a[i+1][j]) insert(b+2*p4[j-1]+2*p4[j],v,now);
                    if(a[i][j+1]) insert(b+p4[j],v,now);
                    if(a[i+1][j]) insert(b+p4[j-1],v,now);
                }
                else if(!b1&&b2==1){
                    if(a[i][j+1]) insert(b+p4[j],v,now);
                    if(a[i+1][j]) insert(b-p4[j]+p4[j-1],v,now);
                }
                else if(!b1&&b2==2){
                    insert(b-p4[j]*2,v,now);
                    if(a[i+1][j]) insert(b-2*p4[j]+2*p4[j-1],v,now);
                }
                else if(b1==1&&!b2){
                    if(a[i][j+1]) insert(b-p4[j-1]+p4[j],v,now);
                    if(a[i+1][j]) insert(b+p4[j-1],v,now);
                }
                else if(b1==1&&b2==1){
                    insert(b-p4[j-1]-p4[j],v,now);
                }
                else if(b1==2&&!b2){
                    if(a[i][j+1]) insert(b-2*p4[j-1]+2*p4[j],v,now);
                    insert(b-2*p4[j-1],v,now);
                }
            }
        }
    }
    ll ans=0;
    for(int i=1;i<=tot[now];i++)
        ans=(ans+val[now][i])%P;
    printf("%lld\n",ans);
}
int main(void){
    //freopen("C:\\Users\\86155\\Desktop\\1.in","r",stdin);
    //freopen("C:\\Users\\86155\\Desktop\\1.out","w",stdout);
    p4[0]=1;
    for(int i=1;i<15;i++) p4[i]=p4[i-1]<<2;
    scanf("%d%d",&n,&m);
    if(n<m){
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                char tmp=getchar();
                while(tmp!='_'&&tmp!='*') tmp=getchar();
                if(tmp=='_') a[j][i]=1;
            }
        swap(n,m);
    }
    else {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                char tmp=getchar();
                while(tmp!='_'&&tmp!='*') tmp=getchar();
                if(tmp=='_') a[i][j]=1;
                //printf("%d\n",a[i][j]);
            }
    }
    solve();
}

上一题