F. Number of Subsequences dp 公式推导

F. Number of Subsequences dp

题目大意:

给你一个只包含 \(a,b,c,?\) 的串,可以将 \(?\) 替换为 \(a|b|c\) ,对于每一个可能的串,求出子序列 \(abc\) 的个数,对答案模 \(1e9+7\)

题解:

一开始推了一个非常复杂的式子。

枚举第 \(i\) 个值是 \(b\) ,假设前 \(i-1\)\(n\)\(?\)\(s1\)\(a\) ,假设 \(i+1\) 后面有 \(a\)\(?\)\(s2\)\(c\)

此时的方案数 \(f[i] = \sum_{b=0}^{b=a} \sum_{m=0}^{m=n}(s2+b)*C(a,b)*2^{a-b}*(s1+m)*C(n,m)*2^{n-m}\)

然后容易发现上式子等价于:$[\sum_{b=0}^{b=a} (s2+b)C(a,b)2^{a-b}] * [\sum_{m=0}{m=n}(s1+m)*C(n,m)*2] $

然后就可以看成求 \(i\) 左边的这个值和右边的这个值相乘,左右两边是一样的求法,所以先求一边:

式子拆解:

\(\sum_{m=0}^{m=n}s1*C(n,m)*2^{n-m}+\sum_{m=0}^{m=n}C(n,m)*m*2^{n-m}\)

= \(s1*(1+2)^n + \sum_{m=0}^{m=n}C(n,m)*m*2^{n-m}\)

接下来求解 \(\sum_{i = 0}^{i = n}C(n,i)*i*2^i\)

因为 \(C(n,i)*i = C(n-i,i-1)*n\)

------ 然后就放弃这个方法了,以后再完善吧 ------------

简单版题解:

之前其实写过类似的题目,不过应该是很早之前了

\((x,y)\) 表示 有 \(x\)\(y\)\(a|c\) 的方案数,默认左边为 \(a\) ,右边是 \(c\)

对于一位置的 b,他左边 \((1,1)\) \((1,2)\) \((1,3)\) 如果右边是 \((1,1)\) \((1,2)\)

那么此时的答案应该是 :

1 * 1 * 1 * 1 + 1 * 2 * 1 * 1 + 1 * 3 * 1 * 1 +

1 * 1 * 1 * 2 + 1 * 2 * 1 * 2 + 1 * 3 * 1 * 2

等价于:(1 + 2 + 3) * (1 + 2) = 18

其实就是 左边 所有 方案数 的 a 之和,与右边所有 方案数的 c 之和的乘积

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
typedef long long ll;
const int mod = 1e9+7;
ll lc[maxn],el[maxn];
ll rc[maxn],er[maxn];
// lc 方案数  el 所有 a 的数量
char s[maxn];

int main() {
    int n;
    scanf("%d%s", &n, s + 1);
    for (int i = 2; i <= n; i++) {
        if (s[i - 1] == 'a') lc[i] = max(1ll, lc[i - 1]), el[i] = el[i - 1] + lc[i];
        else if (s[i - 1] == '?') el[i] = max(1ll, el[i - 1] * 3 + lc[i - 1]), lc[i] = max(3ll, lc[i - 1] * 3);
        else lc[i] = lc[i - 1], el[i] = el[i - 1];
        el[i] %= mod, lc[i] %= mod;
    }
    ll ans = 0;
    for (int i = n - 1; i >= 1; i--) {
        if (s[i + 1] == 'c') rc[i] = max(1ll, rc[i + 1]), er[i] = er[i + 1] + rc[i];
        else if (s[i + 1] == '?') er[i] = max(1ll, er[i + 1] * 3 + rc[i + 1]), rc[i] = max(3ll, rc[i + 1] * 3);
        else rc[i] = rc[i + 1], er[i] = er[i + 1];
        er[i] %= mod, rc[i] %= mod;
        if (s[i] == 'b' || s[i] == '?') ans = (ans + el[i] * er[i] % mod) % mod;
    }
    printf("%lld\n", ans);
}

posted @ 2021-03-17 20:38  EchoZQN  阅读(51)  评论(0编辑  收藏  举报