题意:一行人排队买票,一张票50元,有m个持有50面值钞票的人,有n个持有100面值钞票的人。问,有多少种方案能够让窗口可以让前面人的钱把后面人的钱找开来,也就是说持有50面值钞票的人要尽量放在100面值钞票的人的前面。
思路:持有50面值钞票的人要尽量放在100面值钞票的人的前面。这是一个卡特兰数的模型了。另外因为每个人是不同的,所有结果要乘上
n!
和
m!
,因为结果比较大,我就偷懒选了
java
来写。
http://acm.hdu.edu.cn/showproblem.php?pid=1133
/*********************************************
Problem : HDU 1133
Author : NMfloat
InkTime (c) NM . All Rights Reserved .
********************************************/
import java.io.*;
import java.math.*;
import java.util.*;
public class Main {
public static void main(String argv[]) {
Scanner cin = new Scanner(System.in);
BigInteger [] F = new BigInteger[105];
BigInteger [][] f = new BigInteger[105][105];
for(int i = 0 ; i <= 100 ; i ++) for(int j = 0 ; j <= 100 ; j ++) {
if(j == 0) f[i][j] = BigInteger.ONE;
else f[i][j] = BigInteger.ZERO;
}
F[0] = BigInteger.ONE;
for(int i = 1 ; i <= 100 ; i++) F[i] = F[i-1].multiply(BigInteger.valueOf(i));
for(int i = 1 ; i <= 100 ; i ++) {
for(int j = 1 ; j <= i ; j ++) {
f[i][j] = f[i-1][j].add(f[i][j-1]);
}
}
int n , m;
int CASE = 1;
while(cin.hasNext()) {
n = cin.nextInt();
m = cin.nextInt();
if(n == 0 && m == 0) break;
System.out.printf("Test #%d:\r\n",CASE++);
System.out.println(f[n][m].multiply(F[n]).multiply(F[m]));
}
}
}