先模拟了一下,发现符合卡特兰数。
卡特兰数又称卡塔兰数,英文名Catalan number,是组合数学中一个常出现在各种计数问题中出现的数列。由以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)命名,其前几项为 : 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, ...
令h(0)=1,h(1)=1,catalan数满足递推式
:
h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2)
例如:h(2)=h(0)*h(1)+h(1)*h(0)=1*1+1*1=2
h(3)=h(0)*h(2)+h(1)*h(1)+h(2)*h(0)=1*2+1*1+2*1=5
另类递推式
:
h(n)=h(n-1)*(4*n-2)/(n+1);
递推关系的解为:
h(n)=C(2n,n)/(n+1) (n=0,1,2,...)
递推关系的另类解为:
h(n)=c(2n,n)-c(2n,n+1)(n=0,1,2,...)
#include <stdio.h>
#include <iostream>
#include <string>
#include <string.h>
#include <algorithm>
#include <stdlib.h>
#include <math.h>
#include <vector>
#include <map>
using namespace std;
typedef long long ll;
const int mod = 1000000007;
const int maxn = 1002;
int n,ans;
ll h[maxn];
void dfs(int r,int c){//先模拟一下发现规律
if(r > n/2||c > n/2||r < c)
return;
if(r + c == n){
ans++;
ans %= mod;
}
//printf("%d %d\n",r,c);
dfs(r+1, c);
dfs(r, c+1);
}
int main(){
/*
令h(0)=1,h(1)=1,catalan数满足递推式
h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2)
例如:h(2)=h(0)*h(1)+h(1)*h(0)=1*1+1*1=2
h(3)=h(0)*h(2)+h(1)*h(1)+h(2)*h(0)=1*2+1*1+2*1=5
*/
h[0] = 1;
h[1] = 1;
for(int i=2;i<=500;i++){
h[i]=0;
ll temp=0;
for(int j=1;j<=i;j++){
temp+=(h[j-1]*h[i-j])%mod;
}
h[i]=temp%mod;
}
while(~scanf("%d",&n)){
// ans = 0;
// dfs(0, 0);
// printf("%d\n",ans);
if(n&1)
printf("0\n");
else
printf("%lld\n",h[n/2]);
}
return 0;
}
也可以利用动态规划来求解:
状态 dp[i][j](i <= j) 表示入栈 j 次出栈 i 次的最大种类数
状态转移方程: dp[i][j] = dp[i-1][j] + dp[i][j-1] 。
int dp[maxn][maxn];
for(int j=0;j<=n/2;j++){
dp[0][j] = 1;
}
for(int i=1;i<=n/2;i++){
for(int j=i;j<=n/2;j++){
dp[i][j] = dp[i-1][j]+dp[i][j-1];//利用递推的思想
dp[i][j] %= mod;
}
}
printf("%d\n",dp[n/2][n/2]);