卡特兰数 HDU2067 & HDU4165 & HDU1134
题目链接:https://vjudge.net/problem/HDU-2067
小兔的棋盘
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 11800 Accepted Submission(s): 5952
题解:
2.卡特兰数计算公式:
1) h(n) = h(0)*h(n-1) + h(1)*h(n-2) + ... + h(n-1)h(0) (n>=1) , 其中 h[0] = 1;
2) h(n) = c(2n,n) - c(2n,n+1)(n=0,1,2,...) <==> h(n) = C(2n,n)/(n+1)
3) h(n) = h(n-1)*(4*n-2) / (i+1) ……此条计算公式容易溢出
注意:卡特兰数的计算很容易溢出。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 2e9; 15 const LL LNF = 9e18; 16 const int MOD = 1e9+7; 17 const int MAXN = 35+10; 18 19 LL h[MAXN]; 20 21 void init() 22 { 23 memset(h, 0, sizeof(h)); 24 h[0] = 1; h[1] = 1; 25 for(int i = 2; i<MAXN; i++) 26 for(int j = 0; j<i; j++) 27 h[i] += 1LL*h[j]*h[i-j-1]; 28 } 29 30 int main() 31 { 32 init(); 33 int kase = 0, n; 34 while(scanf("%d", &n) && n!=-1) 35 printf("%d %d %lld\n", ++kase, n, 2LL*h[n]); 36 }
题目链接: https://vjudge.net/problem/HDU-4165
Pills
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1626 Accepted Submission(s): 1139
On the first day, she removes a random pill, breaks it in two halves, takes one half and puts the other half back into the bottle.
On subsequent days, she removes a random piece (which can be either a whole pill or half a pill) from the bottle. If it is half a pill, she takes it. If it is a whole pill, she takes one half and puts the other half back into the bottle.
In how many ways can she empty the bottle? We represent the sequence of pills removed from the bottle in the course of 2N days as a string, where the i-th character is W if a whole pill was chosen on the i-th day, and H if a half pill was chosen (0 <= i < 2N). How many different valid strings are there that empty the bottle?
题解:
有n片药,每天吃半片。当天要么在药罐中抽到把一片完整的药片,然后分成两半,吃一半,最后把另一半放回药罐中;要么抽到半片药片直接吃。问:有多少种情况? 单纯的卡特兰数。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 2e9; 15 const LL LNF = 9e18; 16 const int MOD = 1e9+7; 17 const int MAXN = 30+10; 18 19 LL h[MAXN]; 20 21 void init() 22 { 23 memset(h, 0, sizeof(h)); 24 h[0] = 1; 25 for(int i = 1; i<MAXN; i++) 26 for(int j = 0; j<i; j++) 27 h[i] += 1LL*h[j]*h[i-j-1]; 28 } 29 30 int main() 31 { 32 init(); 33 int n; 34 while(scanf("%d", &n) && n) 35 printf("%lld\n", h[n]); 36 }
题目链接:https://vjudge.net/problem/HDU-1134
Game of Connections
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5112 Accepted Submission(s): 2934
It's still a simple game, isn't it? But after you've written down the 2n numbers, can you tell me in how many different ways can you connect the numbers into pairs? Life is harder, right?
题意:
1~2*n 顺时针排列成一圈, 用n条线段连接n对数,要求线段不能有交叉,问:有多少种连接情况?
题解:
可以将此题联想到出栈问题,这样就转化成卡特兰数了。
递推式一:
1 import java.util.Scanner; 2 import java.math.BigInteger; 3 4 public class Main { 5 6 public static void main(String[] args){ 7 8 BigInteger[] a = new BigInteger[105]; 9 10 a[0] = BigInteger.ONE; 11 for(int i=1; i<=100; i++) { 12 a[i] = BigInteger.valueOf(0); 13 for(int j=0;j<i;j++){ 14 a[i] = a[i].add(a[j].multiply(a[i-j-1])); 15 } 16 } 17 18 Scanner input = new Scanner(System.in); 19 while(input.hasNext()){ 20 int n=input.nextInt(); 21 if(n==-1) break; 22 System.out.println(a[n]); 23 } 24 } 25 }
递推式二:
1 import java.util.Scanner; 2 import java.math.BigInteger; 3 4 public class Main { 5 6 public static void main(String[] args){ 7 8 BigInteger[] a = new BigInteger[105]; 9 10 a[0] = BigInteger.ONE; 11 for(int i=1; i<=100; i++) { 12 a[i] = a[i-1].multiply(BigInteger.valueOf(4*i-2)).divide(BigInteger.valueOf(i+1)); 13 } 14 15 Scanner input = new Scanner(System.in); 16 while(input.hasNext()){ 17 int n=input.nextInt(); 18 if(n==-1) break; 19 System.out.println(a[n]); 20 } 21 } 22 }