• [luogu]P2167 [SDOI2009]Bill的挑战


    原题链接:P2167 [SDOI2009]Bill的挑战

    题意

    有$n(le 15)$个等长字符串,由小写字母和'?'构成,'?'任意匹配。

    求有多少个字符串与刚好$k$个匹配。

    分析

    做了好久然后发现没有这么难,想复杂了。

    原来想法是$f[i][j][S]$表示匹配到前$i$个字母,第$i$个字母为$j$,最大匹配集合为$S$的方案数。

    然后发现第二个条件没有用。删掉就行了。

    状态转移方程?

    对于每个$S$,枚举下一个字母,然后与$S$中的串进行匹配,寻找交集,直接加上去就行了。

    代码

     1 #include <bits/stdc++.h>
     2 #define Mid ((l + r) >> 1)
     3 #define lson (rt << 1)
     4 #define rson (rt << 1 | 1)
     5 using namespace std;
     6 const int mod = 1e6 + 3;
     7 int read(){
     8     char c; int num, f = 1;
     9     while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
    10     while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';;
    11     return f * num;
    12 }
    13 int n, m, k, f[59][1 << 15], len[59], maxn;
    14 int a[15][59], pcnt[1 << 15];
    15 char c[59];
    16 void up(int &a, int b){
    17     a = (a + b);
    18     if(a > mod) a -= mod;
    19 }
    20 void work(){
    21     memset(f, 0, sizeof(f));
    22     n = read(); k = read();
    23     for(int i = 0; i < n; i++){
    24         scanf("%s", c + 1);
    25         m = strlen(c + 1);
    26         for(int j = 1; j <= m; j++){
    27             if(c[j] == '?') a[i][j] = 26;
    28             else a[i][j] = c[j] - 'a';
    29         }
    30     }
    31     for(int i = 0; i < 1 << n; i++)
    32         pcnt[i] = pcnt[i >> 1] + (i & 1);
    33     f[0][(1 << n) - 1] = 1;
    34     for(int i = 0; i < m; i++){
    35         for(int s = 0; s < 1 << n; s++)if(f[i][s]){
    36             for(int j = 0; j < 26; j++){
    37                 int mask = 0;
    38                 for(int p = 0; p < n; p++) if(s & 1 << p)
    39                     if(a[p][i + 1] == 26 || a[p][i + 1] == j)
    40                         mask |= 1 << p;
    41                 up(f[i + 1][mask], f[i][s]);
    42             }
    43         }
    44     }
    45     int ans = 0;
    46     for(int i = 0; i < 1 << n; i++){
    47         if(pcnt[i] == k)
    48             up(ans, f[m][i]);
    49         
    50     }
    51     printf("%d
    ", ans);
    52 }
    53 main()
    54 {
    55     int Case = read();
    56     while(Case--) work();
    57     return 0;
    58 }
    59 /*
    60 f[i][s]表示匹配到前i位,匹配的状态为s的方案数
    61 
    62 */
    View Code
  • 相关阅读:
    Linux菜鸟级重点
    在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误
    搭建PHP开发环境
    Struts+Hibernate+Spring实现用户登录功能
    Struts2整合Hibernate3实现用户登录功能
    决战JS(二)
    决战JS
    lightoj-1098
    lightoj-1072
    lightoj-1094 Farthest Nodes in a Tree(求树的直径)
  • 原文地址:https://www.cnblogs.com/onglublog/p/14186928.html
Copyright © 2020-2023  润新知