Codeforces 356D Bacterial Melee dp

Bacterial Melee

我们发现所有合法串都是原序列的某个子序列(这个子序列相邻元素相等) 的扩展, 比如子序列为abc, 那么aabbbc, abbbcc 等都是合法串。

所以我们只需要dp出原串有多少相邻元素不同的子序列就好啦。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long
using namespace std;

const int N = 5000 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;

int n, f[N][26], g[N][26];
int comb[N][N];
char s[N];
bool vis[26];

inline void add(int &a, int b) {
    a += b; if(a >= mod) a -= mod;
}

int main() {
    for(int i = 0; i < N; i++)
        for(int j = comb[i][0] = 1; j <= i; j++)
            comb[i][j] = (comb[i - 1][j - 1] + comb[i - 1][j]) % mod;
    scanf("%d%s", &n, s + 1);
    f[1][s[1] - 'a'] = 1; vis[s[1] - 'a'] = true;
    for(int i = 2; i <= n; i++) {
        memcpy(g, f, sizeof(g));
        for(int j = i - 1; j >= 1; j--) {
            for(int k = 0; k < 26; k++) {
                if(k != s[i] - 'a') add(f[j + 1][s[i] - 'a'], g[j][k]);
            }
            add(f[j + 1][s[i] - 'a'], mod - g[j + 1][s[i] - 'a']);
        }
        if(!vis[s[i] - 'a']) {
            vis[s[i] - 'a'] = true;
            f[1][s[i] - 'a'] = 1;
        }
    }
    int ans = 0;
    for(int i = 1; i <= n; i++)
        for(int j = 0; j < 26; j++)
            add(ans, 1ll * comb[n - 1][i - 1] * f[i][j] % mod);
    printf("%d\n", ans);
    return 0;
}

/*
*/

猜你喜欢

转载自www.cnblogs.com/CJLHY/p/10508250.html