HDU1133 Buy the Ticket —— 卡特兰数
题目链接:https://vjudge.net/problem/HDU-1133
Buy the Ticket
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 7427 Accepted Submission(s): 3105
Suppose the cinema only has one ticket-office and the price for per-ticket is 50 dollars. The queue for buying the tickets is consisted of m + n persons (m persons each only has the 50-dollar bill and n persons each only has the 100-dollar bill).
Now the problem for you is to calculate the number of different ways of the queue that the buying process won't be stopped from the first person till the last person.
Note: initially the ticket-office has no money.
The buying process will be stopped on the occasion that the ticket-office has no 50-dollar bill but the first person of the queue only has the 100-dollar bill.
题意:
电影票50元一张,有m个拿着50元和n个拿着100元的人去买票。开始时售票处没有一分钱(即开始时不能为100元的找钱),问:这m+n个人应该怎么排队,才能使得每个人都能买到票(即都能找钱或不用找钱)?
题意:
1. 当m<n时,肯定不能满足条件,因为50元的张数小于100元的张数,所以不能为所以的100元找回50元。
2. 当m>=n时,通过合理的安排,就能满足条件:
2.1 首先所有的排列数为 C[m+n][m],即从m+n个位置中挑选m个,作为50元的位置。
2.2 然后排除掉非法排列:假设第k个100元不能找钱, 则前面有k-1个50元,所以后面有n-k个100元, m-k+1个50元,如果把第k个之后的人50换成100,100换成50,那么总的就变成了有:m+1个100元, n-1个50元,那么C[m+n][m+1]就是非法的排列数。
2.3 所以合法的排列数为:C[m+n][m] - C[m+n][m+1],由于人是有区别的, 所以还需要乘上两种人的全排列,所以 ans = (C[m+n][m] - C[m+n][m+1])*A[m]*A[n]。
代码如下:
1 //package main; 2 import java.util.Scanner; 3 import java.math.BigInteger; 4 5 public class Main { 6 7 public static void main(String[] args){ 8 9 BigInteger[] A = new BigInteger[105]; 10 BigInteger[][] C = new BigInteger[205][205]; 11 12 A[0] = BigInteger.valueOf(1); 13 for(int i = 1; i<=100; i++) { 14 A[i] = A[i-1].multiply(BigInteger.valueOf(i)); 15 } 16 17 for(int i = 0; i<=200; i++) 18 for(int j = 0; j<=200; j++) 19 C[i][j] = BigInteger.valueOf(0); 20 21 for(int i = 0; i<=200; i++) { 22 C[i][0] = BigInteger.valueOf(1); 23 for(int j = 1; j<=i; j++) { 24 C[i][j] = C[i-1][j].add(C[i-1][j-1]); 25 } 26 } 27 28 int kase = 0; 29 Scanner input = new Scanner(System.in); 30 while(input.hasNext()){ 31 int m = input.nextInt(); 32 int n = input.nextInt(); 33 if(m+n==0) break; 34 System.out.println("Test #"+(++kase)+":"); 35 BigInteger ans = BigInteger.ZERO; 36 if(m>=n) { 37 ans = A[m].multiply(A[n].multiply((C[m+n][m].subtract(C[m+n][m+1])))); 38 } 39 System.out.println(ans); 40 } 41 } 42 }