zoukankan      html  css  js  c++  java
  • 洛谷 P2167 [SDOI2009]Bill的挑战

    Sheng_bill 不仅有惊人的心算能力,还可以轻松地完成各种统计。在昨天的比赛中,你凭借优秀的程序与他打成了平局,这导致 Sheng_bill 极度的不满。于是他再次挑战你。这次你可不能输。

    这次,比赛规则是这样的:

    给出 (N) 个长度相同的字符串(由小写英文字母和 ? 组成),(S_1,S_2,dots,S_N),求与这 (N) 个串中的刚好 (K) 个串匹配的字符串 (T) 的个数,答案对 (1000003) 取模。

    若字符串 (S_x(1le xle N))(T) 匹配,满足以下条件:

    1. (|S_x|=|T|)
    2. 对于任意的 (1le ile|S_x|),满足 (S_x[i]= exttt{?}) 或者 (S_x[i]=T[i])

    其中 (T) 只包含小写英文字母。

    (1le Tle 5)(1le N le15)(1le|S_i|le50)


    其实就是问有多少种字符串可以和恰好 (k) 个字符串匹配。

    考虑容斥,设 (f_S) 表示只有 (S) 这个集合中的数匹配的方案数,设 (g_S) 表示至少有 (S) 这个集合中的数的匹配的方案数,那么就有,设 (q_x) 表示一个大小为 (x) 的集合的容斥系数:

    [ans=sum_{|S|=k}f_S ]

    [f_S=sum_{Sin T}q_{|T|}g_T ]

    然后考虑算 (q_x) ,因为 (xge k) ,所以考虑大小为 (x) 的集合 (T) 中一个物品对 (S) 的贡献,那么这个的容斥系数是:

    [q_x=sum_{i=k}^{x}{x-kchoose {i-k}}(-1)^{i-k}=sum_{i=0}^{x-k}{x-kchoose i}(-1)^{i} ]

    [=(-1+1)^{x-k} ]

    只有 (x=k)(q_x=1)

    所以最后的答案就是这个式子:

    [ans=sum_{|S|ge k}{|S|choose |S|-k}(-1)^{|S|-k}g(S) ]

    然后考虑怎么算 (g(s)) ,直接看每一位是不是一样的,如果都是 (?) ,说明这个位置有 (26) 种选择,所以记 (x) 为都是 (?) 的位数的个数,(g(s)=26^x)

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    const int N = 50;
    const int M = 15;
    const int p = 1e6 + 3;
    using namespace std;
    int T,n,k,len,ans,cnt[1 << M],C[M + 5][M + 5],m2[N + 5];
    char ch[M + 5][N + 5];
    void prework()
    {
        for (int s = 0;s < (1 << M);s++)
            for (int j = 0;j < M;j++)
                if ((s >> j) & 1)
                    cnt[s]++;
        for (int i = 1;i <= M;i++)
        {
            C[i][0] = C[0][i] = 1;
            for (int j = 1;j <= i;j++)
                C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % p;
        }
        m2[0] = 1;
        for (int i = 1;i <= N;i++)
            m2[i] = 26ll * m2[i - 1] % p;
    }
    int g(int S)
    {
        int sw = 0;
        for (int l = 1;l <= len;l++)
        {
            int fl = 1;
            char chr = 0;
            for (int i = 1;i <= n;i++)
                if ((S >> i - 1) & 1)
                {
                    if (!chr && ch[i][l] == '?')
                    {
                        chr = '?';
                        fl = 2;
                        continue;
                    }
                    if (!chr)
                    {
                        chr = ch[i][l];
                        continue;
                    }
                    if (chr == '?' && ch[i][l] != '?')
                    {
                        chr = ch[i][l];
                        fl = 1;
                        continue;
                    }
                    if (chr != '?' && ch[i][l] == '?')
                        continue;
                    if (chr != '?' && ch[i][l] != chr)
                    {
                        fl = 0;
                        break;
                    }
                }
            if (!fl)
                return 0;
            if (fl == 2)
                sw++;
        }
        return m2[sw];
    }
    int main()
    {
        scanf("%d",&T);
        prework();
        while (T--)
        {
            scanf("%d%d",&n,&k);
            for (int i = 1;i <= n;i++)
                scanf("%s",ch[i] + 1);
            len = strlen(ch[n] + 1);
            ans = 0;
            for (int s = 0;s < (1 << n);s++)
            {
                if (cnt[s] < k)
                    continue;
                ans += 1ll * C[cnt[s]][k] * (((cnt[s] - k) % 2 == 0) ? 1 : -1) * g(s) % p;
                ans %= p;
            }
            printf("%d
    ",(ans + p) % p);
        }
        return 0;
    }
    
  • 相关阅读:
    python count函数
    kubenetes服务发现
    k8s网络
    k8s创建pod流程
    openstack创建虚拟流程、各组件介绍
    生产者消费者问题
    Date类和Calendar类
    Timer定时器
    Java中的克隆
    注解
  • 原文地址:https://www.cnblogs.com/sdlang/p/14284289.html
Copyright © 2011-2022 走看看