P7263 Something Comforting 题解

link

题意简述:
给出一个生成括号序列的方式如下

#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}}\)

posted @ 2021-01-11 21:22  ctt2006  阅读(79)  评论(0)    收藏  举报