洛谷P1722 矩阵Ⅱ (卡塔兰数)

洛谷P1722 矩阵Ⅱ 卡塔兰数

题面

给定一个1*(2n)的矩阵。现让你放入一样多的红色算筹和黑色算筹,使对于所有的i(1<=i<=2n),使第1~i格中红色算筹个数大于等于黑色算筹

(同P1044栈)

思路

记红为R,黑为B,输入n时的结果为Cn
画几个之后,发现这个问题具有子结构。

如n-1的情况可以通过在后面补一个RB构成n的情况。
但若要推导递推公式,需要更确定的子结构划分。
注意,不能通过删去n情况的末尾两个形成n-1的情况,因为不知道n-1内是不是恰好有n-1个R和B
如情况RRRRR...BBBBB(n个红,n个黑),结果是Cn,但删去末尾两个后得不到Cn-1

注意到最末的格子必为黑色,而且它前面未必是红,所以在划分的时候不应包含它。(完整的RB+完整的RB=完整的RB,完整的RB才可应用Ci递推)
现在序列中多余了一个红色的元素,也不应包含(和末尾B配对的R)。这样,剩下的部分就是完整部分。

划分
配对RB列的种类数是Ci ,其中i是列长度

这种R有n-1个可能存在的位置,即1 ~ n-1,不同的情况符合加法原理

前面的RB列长0时,后面RB列长n-1(实际长度为2倍,这里说的是输入为相应规模的子问题)
以此类推
所以
a n s = C 0 C n 1 + C 1 C n 2 + . . . + C n 2 C 1 + C n 1 C 0 ans=C_0C_{n-1}+C_1C_{n-2}+...+C_{n-2}C_1+C_{n-1}C_0
这就是卡塔兰数定义
从小到大打表即可
这个过程和括号配对种数问题,栈出列种数问题是等价的,在寻找和末尾B配对的R时就应当发现了。

代码

#include <stdio.h>
#include<iostream>
using namespace std;
int C[105];
int main()
{
	ios::sync_with_stdio(false);
	C[0] = 1;C[1] = 1;C[2] = 2;
	for (int i = 3; i <=100 ; i++)//打表
	{
		for (int j = 0, k = i - 1;j <= i - 1;j++, k--) {
			C[i] += C[j] * C[k] % 100;
		}
		C[i] %= 100;//分步取模
	}
	int n;
	cin >> n;
	cout << C[n];
	return 0;
}
发布了32 篇原创文章 · 获赞 0 · 访问量 1202

猜你喜欢

转载自blog.csdn.net/engineoid/article/details/104088669
今日推荐