1 条题解

  • 0
    @ 2026-5-18 21:51:55

    B. 曾为财务官,今助地精欺 详细题解

    一、题目理解

    给定一个由字符 '-''_' 组成的字符串,可以任意重新排列。定义字符串的值为其中等于 "-_-"不同子序列的个数。

    目标:通过最优重排,最大化这个值。

    子序列 "-_-" 由三个字符组成:第 11 和第 33 个必须是 '-',第 22 个必须是 '_'

    由于可以任意排列,我们只关心两种字符的总数,不关心它们原来的顺序。


    二、核心观察

    设:

    • aa = 字符串中 '-' 的总个数
    • bb = 字符串中 '_' 的总个数

    显然 a+b=na + b = n


    三、子序列计数公式

    在固定排列下,子序列 "-_-" 的个数可以通过以下方式计算:

    选择中间的那个 '_',然后从它左边选一个 '-',从它右边选一个 '-'

    bb'_' 的位置从左到右为 p1,p2,,pbp_1, p_2, \dots, p_b
    对于第 ii'_',设它左边有 LiL_i'-',右边有 RiR_i 个 `'-'$,则它贡献的子序列数为:

    LiRiL_i \cdot R_i

    总数为:

    i=1bLiRi\sum_{i=1}^{b} L_i \cdot R_i

    四、最大化策略

    为了最大化 LiRi\sum L_i \cdot R_i,应该将所有 '_' 放在中间连续的一段'-' 放在两端。

    为什么?
    设左边放 xx'-',右边放 axa - x'-'
    由于所有 '_' 在中间,每个 '_' 的左边都有相同的 xx'-',右边都有相同的 axa-x'-'

    因此:

    总数=bx(ax)\text{总数} = b \cdot x \cdot (a - x)

    这是一个关于 xx 的二次函数:

    f(x)=b(x2+ax)f(x) = b \cdot ( -x^2 + a x )

    开口向下,最大值在 x=a2x = \frac{a}{2} 处取得。


    五、公式推导

    由于 xx 必须是整数,最优取法为:

    x=a2x = \left\lfloor \frac{a}{2} \right\rfloor

    此时:

    $$\text{最大值} = b \cdot \left\lfloor \frac{a}{2} \right\rfloor \cdot \left(a - \left\lfloor \frac{a}{2} \right\rfloor\right) $$

    注意到 aa/2=a/2a - \lfloor a/2 \rfloor = \lceil a/2 \rceil

    因此:

    $$\boxed{\text{ans} = b \cdot \left\lfloor \frac{a}{2} \right\rfloor \cdot \left\lceil \frac{a}{2} \right\rceil} $$

    六、边界情况

    • 如果 a<2a < 2'-' 少于 22 个),无法构成 "-_-",此时 a/2=0\lfloor a/2 \rfloor = 0,公式自动给出 00
    • 如果 b=0b = 0(没有 '_'),公式自动给出 00
    • 如果 n<3n < 3,公式也自动给出 00

    七、算法步骤

    1. 读入 nn 和字符串 ss
    2. 统计 '-' 的个数 aa(可用 count 函数)
    3. 计算 b=nab = n - a
    4. 输出 $b \cdot \lfloor a/2 \rfloor \cdot \lceil a/2 \rceil$

    八、标程代码解析

    void solve() {
      int n;
      string s;
      cin >> n >> s;
      int64_t dash = count(s.begin(), s.end(), '-');   // a
      int64_t under = n - dash;                        // b
      int64_t ans = (dash / 2) * (dash - dash / 2) * under;
      // dash/2 是 floor(a/2)
      // dash - dash/2 是 ceil(a/2)
      cout << ans << '\n';
    }
    

    注意 int64_t 的使用,防止乘法溢出(n2×105n \le 2\times 10^5 时最大答案约 101510^{15},需要 64 位整数)。


    九、复杂度分析

    • 统计字符:O(n)O(n)
    • 计算答案:O(1)O(1)
    • 每个测试用例 O(n)O(n),总复杂度 O(n)2×105O(\sum n) \le 2\times 10^5

    十、总结

    要点 说明
    核心公式 $\text{ans} = b \cdot \lfloor a/2 \rfloor \cdot \lceil a/2 \rceil$
    最优构造 所有 '_' 放在中间,'-' 均匀分到两边
    时间复杂度 O(n)O(n) 每个测试用例
    空间复杂度 O(1)O(1) 额外空间
    注意事项 使用 64 位整数存储答案
    • 1

    信息

    ID
    7240
    时间
    1000ms
    内存
    256MiB
    难度
    5
    标签
    递交数
    1
    已通过
    1
    上传者