zoukankan      html  css  js  c++  java
  • abc215_e Chain Contestant(状压dp)

    题目链接

    题目大意

      给你一个字符串,问你有多少子序列s,满足相同的字符都是连续出现的,当两个子序列中有一个字符的位置不同时两个子序列不同。

    解题思路

      看到只有10种字符,并且n只有1000大概就能想到做法了。考虑dp,对于当前字符i,如果之前有一个以i结尾的合法子序列,那么在它后面加上i也是合法的;如果不是以i结尾的子序列,那么之前就不能出现i,否则相同字符不能连续出现。所以我们需要记录两样东西,一样是前面出现的字符集合,一样是字符集合中结尾的字符,前者可以用10位二进制表示,后者用10个int表示即可。
      有一个小细节需要注意一下,我们不能只考虑从前面的状态转移到当前的状态,因为还有一种方案,是前面没有字符,只有当前一个字符,记得补上去。

    代码

    const int maxn = 1e3+10;
    const int maxm = 2e5+10;
    int dp[2][1<<10][10];
    int main() {
        IOS;
        int n; cin >> n;
        string s; cin >> s;
        for (int i = 0; i<n; ++i) {
            int t = s[i]-'A';
            int now = i&1, pre = now^1;
            memcpy(dp[now], dp[pre], sizeof(dp[pre]));
            ++dp[now][1<<t][t];
            for (int j = 0; j<(1<<10); ++j)
                if (j&(1<<t)) {
                    for (int k = 0; k<10; ++k) {
                        if (k==t) dp[now][j][t] += dp[pre][j][k];
                        else dp[now][j][t] += dp[pre][j^(1<<t)][k];
                        dp[now][j][t] %= MOD;
                    }
                }
        }
        int ans = 0;
        for (int i = 0; i<(1<<10); ++i)
            for (int j = 0; j<10; ++j)
                ans = (ans+dp[(n-1)&1][i][j])%MOD;
        cout << ans << endl;
        return 0;
    }
    
  • 相关阅读:
    MySQL库表设计小技巧
    教你用SQL实现统计排名
    Truncate用法详解
    utf8字符集下的比较规则
    关于Aborted connection告警日志的分析
    MySQL DDL详情揭露
    时间戳,这样用就对了
    在线修改主从复制选项
    20181211HW
    20181207hw
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/15651924.html
Copyright © 2011-2022 走看看