迟来的正义.....
ummmm,此题不会,全排列爆炸的可能
对于卡特兰数并没有理解....
f(n)=f(0)*f(n-1)+f(1)*f(n-2)......f(n-1)*f(0);
---------------------------------------------------------
首先,我们设f(n)=序列个数为n的出栈序列种数。(我们假定,最后出栈的元素为k,显然,k取不同值时的情况是相互独立的,也就是求出每种k最后出栈的情况数后可用加法原则,由于k最后出栈,因此,在k入栈之前,比k小的值均出栈,此处情况有f(k-1)种,而之后比k大的值入栈,且都在k之前出栈,因此有f(n-k)种方式,由于比k小和比k大的值入栈出栈情况是相互独立的,此处可用乘法原则,f(n-k)*f(k-1)种,求和便是Catalan递归式。
这题特么....看错了,整个思路基于假设【最后出栈的元素为k】,我看成了假设第一个出栈元素是K,那么f(n-k)可以理解,前面的怎么也想不出来是怎么回事为什会是f(k-1)........
此题由于前面的可以推出是卡特兰数,做时候要用
另类递推式:
h(n)=h(n-1)*(4*n-2)/(n+1);
本题基本就是得到这个公式然后大数数组的乘法和除法运算即可.....
有点难受................想到爆炸也想不到的.................
如果说得到了上述的推式,那么一切都好办了,做的时候按部就班的算即可,先算(4*n-2)/(n+1) 然后在和h(n-1)做乘法,咋看感觉很好,少了一次大数除法,我开始就是这么想的,但是当n=3时候 (4*n-2)/(n+1)=2.5..... 2.5和h(n-1)做乘法会丢失数据,是个坑【可能是我并不会小数点和数组做乘法有关,如果分数可以和数组的数做乘法那么这个方法还是比较好的】
AC代码如下:
# include<iostream>
using namespace std;
int C[200][200];//C[n][0]表示n的卡特兰数的长度,存储是反向的,C[n][1]表示个位数
void Catalan(void) {
C[0][0] = C[0][1] = 1;
C[1][0] = C[1][1] = 1;
int carry,digit,sum;
double t;
for (int i = 2; i < 101; i++)//去碰一下 i=2 的坑
{
t = (4 * i - 2);
carry = sum = 0;
//只需要求 h(i-1)并分为存储
for (int j = 1; j <= C[i - 1][0]; ++j)//C[i-1][0] 为 h(i-1)的长度
{
sum = C[i - 1][j] * t + carry;
C[i][j] = sum % 10;
carry = sum / 10;
}
digit = C[i - 1][0];
while (carry) {//此时位数开始在原基础上增加
digit++;
C[i][digit] = carry % 10;
carry /= 10;
}
//此时已经求出了 h(n-1)*(4*n-2) 接着 /(n+1);
for (int j = digit; j > 0; j--) {
sum = C[i][j] + carry * 10;
C[i][j] = sum / (i + 1);
carry = sum % (i + 1);
}
while (!C[i][digit]) {
digit--;
}
C[i][0] = digit;
}
}
int main(void) {
int N;//火车数
Catalan();
while (cin >> N) {//非整形退出
if (N <= 0)
return 0;
for (int i = C[N][0]; i > 0; i--) {
cout << C[N][i];
}
cout << endl;
}
system("pause");
return 0;
}