P11655 「FAOI-R5」Lovely 139 解题报告


P11655 「FAOI-R5」Lovely 139 解题报告

一、 题目分析

首先,我们来弄清楚题目要求的是什么。

  1. 01串:一个只包含字符 '0' 和 '1' 的字符串。
  2. 极长颜色段:简单来说,就是连续的、相同字符的最长子串。比如 000110 中,000110 就是三个极长颜色段。
  3. \(g(S)\):一个 01 串 \(S\) 中,不同的极长颜色段的数量。
    • 例如 \(g(\underline{00}) = 1\)
    • 例如 \(g(\underline{111}\underline{0}) = 2\)
    • 例如 \(g(\underline{00}\underline{1}\underline{0}\underline{11}) = 4\)
  4. \(f(n, m)\):核心要求。我们需要计算所有恰好包含 \(n\) 个 '0' 和 \(m\) 个 '1' 的 01 串的 \(g(S)\) 之和。

举个例子,对于 \(n=2, m=2\),所有可能的 01 串有 \(C(4,2)=6\) 种:
0011 -> \(g=2\)
0101 -> \(g=4\)
0110 -> \(g=3\)
1001 -> \(g=3\)
1010 -> \(g=4\)
1100 -> \(g=2\)
\(f(2,2) = 2+4+3+3+4+2 = 18\)

直接暴力枚举所有字符串然后计算 \(g(S)\) 再求和,只在 \(n+m\) 很小的时候才可行。对于本题的数据范围,我们需要一个更高效的数学方法。

二、 思路转换:如何计算 \(g(S)\)

我们观察 \(g(S)\) 的计算方式。每当字符串中的颜色发生变化时,就会产生一个新的颜色段。

  • 字符串 1110,在第 3 位和第 4 位之间(从 1 变为 0),颜色发生了一次变化。整个串的颜色段数是 \(1+1=2\)
  • 字符串 001011,在第 2、3 位之间(0->1),第 3、4 位之间(1->0),第 4、5 位之间(0->1),共发生了 3 次颜色变化。整个串的颜色段数是 \(3+1=4\)

我们发现一个规律:
\(g(S) = (\text{相邻字符不同的位置数量}) + 1\)

为什么是 +1 呢?因为即使字符串中没有颜色变化(例如 000111),它本身也构成了一个颜色段。所以,第一个颜色段是“基础分”,之后每发生一次颜色翻转,就增加一个新的颜色段。

这个发现至关重要,它将我们“数段数”的问题,转换为了“数相邻不同字符对”的问题。

三、 贡献法计算:拆分问题

现在,我们的目标是计算 \(\sum g(S)\),根据上面的转换,它等价于计算:

\[\sum_{\text{所有合法S}} ((\text{S中相邻不同字符对的数量}) + 1) \]

根据加法分配律,我们可以把这个和式拆成两部分:

\[\sum_{\text{所有合法S}} 1 \quad + \quad \sum_{\text{所有合法S}} (\text{S中相邻不同字符对的数量}) \]

这是一种经典的组合数学思想,称为“贡献法”。我们分别计算每一部分的贡献,然后相加。

1. 计算第一部分: +1 的总贡献

这部分最简单。对于每一个符合条件的字符串 \(S\)(即包含 \(n\) 个 '0' 和 \(m\) 个 '1'),我们都为总和贡献了 1。所以,我们只需要知道总共有多少个这样的字符串。

这相当于在 \(n+m\) 个位置中,选择 \(n\) 个位置放 '0'(剩下的 \(m\) 个位置自动放 '1')。这是一个经典的组合问题,总共有 \(C_{n+m}^n\) 个不同的字符串。

所以,第一部分的总贡献是:\(C_{n+m}^n\)

2. 计算第二部分:相邻不同字符对的总贡献

这部分稍微复杂一些。我们不想遍历每个字符串再数它有多少个不同对。我们可以反过来思考:对于每一个可能的位置,它对总和贡献了多少?

一个长度为 \(n+m\) 的字符串,有 \(n+m-1\) 个“相邻位置对”(即第1和2位,第2和3位,...,第 \(n+m-1\)\(n+m\) 位)。

我们任意选择一个相邻位置对,比如第 \(i-1\) 位和第 \(i\) 位。在多少个字符串中,这两位是不同的(即 0110)?

  • Case 1: 第 \(i-1\) 位是 '0',第 \(i\) 位是 '1'
    我们已经固定了这两位,用掉了 1 个 '0' 和 1 个 '1'。
    剩下还有 \(n-1\) 个 '0' 和 \(m-1\) 个 '1'。
    总共有 \(n+m-2\) 个空余位置。
    我们需要在剩下的 \(n+m-2\) 个位置中,选择 \(n-1\) 个位置放 '0'。
    方案数是 \(C_{n+m-2}^{n-1}\)

  • Case 2: 第 \(i-1\) 位是 '1',第 \(i\) 位是 '0'
    同理,我们也用掉了 1 个 '1' 和 1 个 '0'。
    剩下还有 \(n-1\) 个 '0' 和 \(m-1\) 个 '1'。
    方案数依然是 \(C_{n+m-2}^{n-1}\)

所以,对于任意一个相邻位置对 \((i-1, i)\),总共有 \(2 \times C_{n+m-2}^{n-1}\) 个字符串在此处发生了颜色变化。

由于一共有 \(n+m-1\) 个这样的相邻位置对,且每个位置对的贡献都是相同的,所以第二部分的总贡献就是:

\[(n+m-1) \times 2 \times C_{n+m-2}^{n-1} \]

四、 总结与公式

将两部分的贡献相加,我们就得到了最终的答案 \(f(n,m)\)

\[f(n,m) = C_{n+m}^n + (n+m-1) \times 2 \times C_{n+m-2}^{n-1} \]

特殊情况处理
如果 \(n=0\)\(m=0\),字符串只有一种(如 111...),颜色段数量为 1。此时 \(f(n,m)=1\)。我们的公式在这种情况下也成立,因为 \(C_{n+m-2}^{n-1}\) 此时的 \(n-1\)\(m-1\) 为负数或大于上标,组合数为 0,第二项消失,只剩下 \(C_{n+m}^n=1\)

如果 \(n+m < 2\),第二项也会因为组合数无意义而为 0,公式依然正确。

五、 代码实现

为了在规定时间内计算出结果,我们需要高效地计算组合数 \(C_a^b \pmod{p}\)。由于模数 \(10^9+7\) 是一个质数,我们可以通过预处理阶乘和阶乘的逆元来实现。

  1. 预处理:计算从 \(1!\)\((2 \times 10^6)!\) 的阶乘值,以及它们的模逆元。
  2. 计算组合数:利用公式 \(C_a^b = \frac{a!}{b!(a-b)!} = a! \times (b!)^{-1} \times ((a-b)! )^{-1} \pmod{p}\)
  3. 代入公式:根据输入的 \(n, m\),利用预处理好的数据和上述公式计算 \(f(n,m)\)

这样,对于每次查询,我们都可以在 \(O(1)\) 的时间内得出答案。


希望这份报告能帮助你理解这道题的巧妙解法!核心就是将一个看似复杂的问题(数颜色段)转换成一个更容易用组合数学处理的问题(数颜色变化点),再利用贡献法将问题分解,最终得到一个优美的计算公式。

posted @ 2025-07-22 14:54  surprise_ying  阅读(16)  评论(0)    收藏  举报