• [BZOJ1879] [Sdoi2009]Bill的挑战


    Description

    Input

    本题包含多组数据。 
    第一行:一个整数T,表示数据的个数。 
    对于每组数据: 
    第一行:两个整数,N和K(含义如题目表述)。 
    接下来N行:每行一个字符串。
    T ≤ 5,M ≤ 15,字符串长度≤ 50。

    Output

    如题

    Sample Input

    5
    3 3
    ???r???
    ???????
    ???????
    3 4
    ???????
    ?????a?
    ???????
    3 3
    ???????
    ?a??j??
    ????aa?
    3 2
    a??????
    ???????
    ???????
    3 2
    ???????
    ???a???
    ????a??

    Sample Output

    914852
    0
    0
    871234
    67018


    容易想到设$large f[i][s]$表示正在填第i为,匹配的状态为s的方案数。

    然后转移就很明显了,预处理出来每一位填每一个字母可以匹配的集合,然后可以快速转移。

    这样做Luogu上AC了,但Bzoj的laji评测机过不去, 所以需要点优化。

    首先小于k的状态不用转移,因为再怎么转移也不会让匹配成功的数目增多。

    还有如果$large f[i][s]$是0,那么就不用它转移, 这样452msAC


    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <bitset>
    #include <ctime>
    using namespace std;
    #define reg register
    #define mod 1000003
    int T;
    int n, m; 
    char S[16][55];
    int f[55][1<<15];
    int g[55][500];
    int bin[16];
    int ans;
    
    int main() 
    {
        bin[0] = 1;for(reg int i = 1 ; i <= 15 ; i ++) bin[i] = bin[i-1] << 1;
        scanf("%d", &T);
        while(T--)
        {
            memset(f, 0, sizeof f);
            memset(g, 0, sizeof g);
            scanf("%d%d", &n, &m);
            for (reg int i = 1 ; i <= n ; i ++) scanf("%s", S[i] + 1);
            int len = strlen(S[1] + 1);
            
            for (reg int i = 1 ; i <= len ; i ++) 
                for (reg int k = 1 ; k <= n ; k ++)
                    if (S[k][i] == '?')  
                        for (reg int j = 'a' ; j <= 'z' ; j ++)g[i][j] |= bin[k-1];
                    else g[i][S[k][i]] |= bin[k-1];
            
            f[0][bin[n]-1] = 1;
            
            for (reg int i = 0 ; i < len ; i ++)
            {
                for (reg int s = 0 ; s <= bin[n] - 1 ; s ++)
                {
                    if (!f[i][s]) continue;
                    bitset <17> bit = s;
                    if (bit.count() < m) continue;
                    for (reg int j = 'a' ; j <= 'z' ; j ++)
                    {
                        int sit = s & g[i+1][j];
                        f[i+1][sit] = (f[i+1][sit] + f[i][s]) % mod;
                    }
                }
            }
            ans = 0;
            for (reg int s = 0 ; s <= bin[n] - 1 ; s++)
            {
                bitset <17> bit = s;
                if (bit.count() == m) ans = (ans + f[len][s]) % mod;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    EntityFramework系列:MySql的RowVersion
    EntityFramework系列:SQLite.CodeFirst自动生成数据库
    怎么回事呢?
    为蛇么不现实
    发布到个人主页
    作别
    budao 首页
    中午吃饱了
    作业写好了吗?
    分类
  • 原文地址:https://www.cnblogs.com/BriMon/p/9585303.html
Copyright © 2020-2023  润新知