加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

【[SDOI2009]Bill的挑战】

发布时间:2020-12-14 05:17:14 所属栏目:大数据 来源:网络整理
导读:这个复杂度能过真是令人惊讶 本来准备是打个暴力看看能水多少分的,但是就 (A) 了 那也就是说我用 (50*2^{15}*26*15) 的复杂度跑过了五组数据 真是玄学 首先字符串题目的套路就是我们需要存一个状态表示匹配到第几位 (n=15) 一眼状压 于是我们的状态是

这个复杂度能过真是令人惊讶

本来准备是打个暴力看看能水多少分的,但是就(A)

那也就是说我用(50*2^{15}*26*15)的复杂度跑过了五组数据

真是玄学

首先字符串题目的套路就是我们需要存一个状态表示匹配到第几位

(n<=15)一眼状压

于是我们的状态是(dp[i][S])表示在(S)这个状态下的所有字符串都匹配到了(i)位的方案数

于是我们可以刷表转移

由于字符集大小只有(26),所以我们可以对于每一个状态枚举一下这个状态往下匹配匹配哪一位

之后在枚举一下当前状态里的所有串,我们就可以得到这一个状态往下扩展的状态是什么了

是个非常大的,但是跑不满的复杂度

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define re register
const int mod=1000003;
int T,n,m,len;
char S[16][51];
inline int cnt(int x)
{
    int tot=0;
    while(x) tot+=(x&1),x>>=1;
    return tot;
}
int dp[51][32768];
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(re int i=1;i<=n;i++)
            scanf("%s",S[i]+1);
        int len=strlen(S[1]+1);
        memset(dp,sizeof(dp));
        int N=(1<<n);
        dp[0][N-1]=1;
        for(re int i=0;i<len;i++)
            for(re int j=0;j<N;j++)
            {
                if(!dp[i][j]) continue;
                for(re char k=‘a‘;k<=‘z‘;k++)
                {
                    int f=j;
                    for(re int p=1;p<=n;p++)
                    if(j&(1<<(p-1))) if(S[p][i+1]!=‘?‘&&S[p][i+1]!=k) f^=(1<<(p-1));
                    dp[i+1][f]=(dp[i+1][f]+dp[i][j])%mod;
                }
            }
        int ans=0;
        for(re int i=0;i<N;i++)
        if(cnt(i)==m) ans=(ans+dp[len][i])%mod;
        std::cout<<ans;
        putchar(10);
    }
    return 0;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读