P7263 Something Comforting 题解
题意简述:
给出一个生成括号序列的方式如下
#include <algorithm>
#include <string>
std::string generate(int n) { // 生成一个长度为 n * 2 的括号序列
const int len = n * 2;
bool arr[len]; // 0 代表左括号,1 代表右括号
for (int i = 0; i < n; ++i) arr[i] = 0;
for (int i = n; i < len; ++i) arr[i] = 1;
std::random_shuffle(arr, arr + len); // 随机打乱这个数组
for (int i = 0, j, sum = 0; i < len; ) {
sum += arr[i]? -1: 1;
if (sum < 0) { // 出现了不合法的位置
for (j = i + 1; j < len; ++j) {
sum += arr[j]? -1: 1;
if (sum == 0) break;
}
// 现在 i 是第一个不合法的位置,j 是 i 后面第一个合法的位置
// ( ( ) ) ) ) ( ( ( ) ( )
// i j
for (int k = i; k <= j; ++k)
arr[k] ^= 1; // 把这段区间全部反转
i = j + 1;
} else ++i;
}
std::string ret;
for (int i = 0; i < len; ++i)
ret += arr[i]? ')': '(';
return ret;
}
再给出一个合法的字符串,求生成这个字符串的概率
Solution:
考虑括号序列在坐标系中的意义,(代表向右上角走,)代表向右下角走,
则一个合法的序列可以转化为折线不经过\(y=-1\),且终点为\((2n,0)\)的路径
再看这段程序,它构造的方式是找到所有在\(x\)轴下方的部分,然后把它们关于\(x\)轴对称
显然不管怎么对称,折线与\(x\)轴的交点是不变的
我们设给出序列与\(x\)轴一共有\(m\)个交点,则共有\(m-1\)段区间,每个区间都有两种可能:在\(x\)轴上方与在\(x\)轴下方,且形状相同
所以能生成这个序列的方式有\(2^{m-1}\)种
答案为\(\frac{2^{m-1}}{\binom{2n}{n}}\)

浙公网安备 33010602011771号