Problem Description
The "Harry Potter and the Goblet of Fire" will be on show in the next few days. As a crazy fan of Harry Potter, you will go to the cinema and have the first sight, won’t you?

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.

 
Input
The input file contains several test cases. Each test case is made up of two integer numbers: m and n. It is terminated by m = n = 0. Otherwise, m, n <=100.
 
Output
For each test case, first print the test number (counting from 1) in one line, then output the number of different ways in another line.
 
Sample Input
3 0
3 1
3 3
0 0
 
Sample Output
Test #1: 6
Test #2: 18
Test #3: 180
 
 
题目意思:电影票50一张,m个人手里恰好有50元,n个人手里只有100元,开始电影售票员手里没有钱,问有多少种排队方式,使得每个人都能买上票。
 
解题思路:为了使得每个人都买上票,手里有50的好说,而手里有100元的需要其排列之前有50的人,这样才会有找回的钱,是不是和入栈出栈问题很像?是的,如果n=m,那么这就是一个卡特兰数的应用,直接套用公式即可,对于这道题,我们需要变换一下。
我们知道如果m<n,必然为0。当m>=n时,如果用0代表拿有50的人,用1代表拿有100的人。我们可以把拿有同一种钞票的人都看成一样的,现在只关注这一种的排列方式,之后再乘上n!和m!来消去把同一种钞票的人看成一种排列方法的影响就行了。
 
如果有这么一个序列 0101101001001111..........  当第K个位置出现1的个数多余0的个数时就是一个不合法序列了 。
假设m=4 n=3的一个序列是:0110100 显然,它不合法, 现在我们把它稍微变化一下:  把第二个1(这个1前面的都是合法的)后面的所有位0变成1,1变成0  就得到 0111011 这个序列1的数量多于0的数量, 显然不合法, 但现在的关键不是看这个序列是不是合法的  关键是:它和我们的不合法序列 0110100 成一一对应的关系  也就是说任意一个不合法序列(m个0,n个1), 都可以由另外一个序列(n-1个0和m+1个1)得到 
另外我们知道,一个序列要么是合法的,要么是不合法的  所以,合法序列数量 = 序列总数量 - 不合法序列的总量 
序列总数可以这样计算m+n 个位置中, 选择 n 个位置出来填上 1, 所以是 C(m+n, n) 
不合法序列的数量就是m+n 个位置中, 选择 m+1 个位置出来填上1, 所以是 C(m+n, m+1) 
然后每个人都是不一样的,所以需要全排列 m! * n!
所以最后的公式就是(C(m+n, n)-C(m+n, m+1))*m!*n! 化简后为 (m+n)!*(m-n+1)/(m+1);
 import java.util.*;
import java.math.BigInteger;
public class Main
{
public static void main(String[] args)
{
int a,b;
Scanner in=new Scanner(System.in);
int cnt=0;
while(in.hasNext())
{
cnt++;
a=in.nextInt();
b=in.nextInt();
BigInteger ans=BigInteger.ONE;
if(a==0&&b==0)break;
if(a<b) ans=BigInteger.ZERO;
else
{
for(int i=1; i<=a+b; i++)
{
ans=ans.multiply(BigInteger.valueOf(i));
}
int mpl=(a-b+1);
int dvd=(a+1);
ans=ans.multiply(BigInteger.valueOf(mpl));
ans=ans.divide(BigInteger.valueOf(dvd));
}
System.out.println("Test #"+cnt+":");
System.out.println(ans);
}
}
}

https://blog.csdn.net/qq_33171970/article/details/50644971

这位大佬的想法也很好,通过一个二维数组构造成一个矩阵,递推打表,看起来很清晰。

这张图真是太棒了。

  题目分析,有n+m个人去买票,m个人拿50,n个人拿100,问有几种安排人排队的方法。明显是一个有关组合的问题,我们先判断一下特殊情况,只有在m>=n的情况下才可能安排排队,否则钱是找不开的,而且n=0时全是拿50的,那直接n的阶乘就好了。在一般情况下,可以列一个n*m的矩阵来表示答案,而且因为只要有几种排队方法确定以后直接乘以n的阶乘和m的阶乘就可以了,所以我们可以把n个人视为一样的,m个人视为一样的。那么就可以确定一般情况时排队方法有多少种。

    则第m+n个人的排队方式可以看做多了第m+n个人,本来已经有了(m+n-1)个人,如果这个人拿的是50,那么就是在((m-1)+n)的基础上多了一个人,此时第m+n个人站在最后面(因为每个人都一样,所以实际上已经考虑了所有的情况),同样,如果这个人拿的是100,那么就是在(m+(n-1))的基础上多了一个人,因为人 都一样,所以又有(m,n-1)这种情况的种类,那么第m+n个人的排队类数就是(m,n-1)和(m-1,n)的和,(事实上如果最后来的那个人不站最后面那么就会出现重复的排队数,你可以试试用笔推一下)。那么递推式就出来了,我们就可以用打表的方法利用递推把m,n个人对应的排队数目用数组存储起来
 我们可以发现,对角线上的数字就是卡特兰数,也就是说如果m=n,那么排队数目就是卡特兰数 。

    之后求阶乘的步骤就不用再说,排队的种类数乘以m的阶乘和n的阶乘就去掉了我们之前把拿同一种钞票的人视为一样的做法的影响了,那么我们得到的就是最终答案了。小提示,求m和n的阶乘的时候即使是0的阶乘也要注意返回一个1,否则当n=0时计算结果就会出现错误~~

 import java.util.*;
import java.math.*;
public class Main
{
public static void main(String[] args)
{
Scanner input=new Scanner(System.in);
BigInteger a=new BigInteger("1");
BigInteger c=new BigInteger("0");
BigInteger ans[][]=new BigInteger[105][105];
for(int i=0; i<=100; i++)
for(int j=0; j<=100; j++)
{
if(i<j) ans[i][j]=c;
else if(j==0) ans[i][j]=a;
else
{
ans[i][j]=ans[i][j-1].add(ans[i-1][j]);
}
}
int count=0;
while(true)
{
int m=input.nextInt(),n=input.nextInt();
if(m==0 && n==0) break;
BigInteger e=new BigInteger("1");
BigInteger f=new BigInteger("0");
for(int i=1; i<=m; i++)
{
f=f.add(a);
e=e.multiply(f);
}
BigInteger g=new BigInteger("1");
BigInteger h=new BigInteger("0");
for(int i=1; i<=n; i++)
{
h=h.add(a);
g=g.multiply(h);
}
BigInteger b=ans[m][n].multiply(e).multiply(g);
System.out.println("Test #"+ ++count+":");
System.out.println(b);
}
}
}

Buy the Ticket HDU 1133 卡特兰数应用+Java大数的更多相关文章

  1. hdu1133 Buy the Ticket (卡兰特数应用+java大数)

    题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=1133 [题意] 电影票50块一张 有m个人手里正好有50块,n个人手里正好有100块,售票厅開始没有 ...

  2. hdu 1133(卡特兰数变形)

      题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1133   题意:排队买50块一张的票,初始票台没有零钱可找,有m个人持有50元,n人持有100元, ...

  3. Buy the Ticket HDU 1133 递推+大数

    题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=1133 题目大意: 有m+n个人去买电影票,每张电影票50元,  m个人是只有50元一张的,  n个人 ...

  4. Buy the Ticket HDU 1133

    传送门 [http://acm.hdu.edu.cn/showproblem.php?pid=1133] 题目描述和分析 代码 #include<iostream> #include< ...

  5. Buy the Ticket HDU - 1133 大数dp

    题意: 演唱会门票售票处,那里最开始没有零钱.每一张门票是50元,人们只会拿着100元和50元去买票,有n个人是拿着50元买票,m个人拿着100元去买票. n+m个人按照某个顺序按序买票,如果一个人拿 ...

  6. hdu 1133 卡特兰 高精度

    Buy the Ticket Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) T ...

  7. hdu 1023 卡特兰数+高精度

    Train Problem II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  8. HDU 4828 (卡特兰数+逆)

    HDU 4828 Grids 思路:能够转化为卡特兰数,先把前n个人标为0.后n个人标为1.然后去全排列,全排列的数列.假设每一个1的前面相应的0大于等于1,那么就是满足的序列,假设把0看成入栈,1看 ...

  9. hdu 1130,hdu 1131(卡特兰数,大数)

    How Many Trees? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

随机推荐

  1. mysql/mariadb学习记录——连接查询(JOIN)

    //本文使用的数据表格//persons表中id_p为主键//orders表中id_o为主键,id_p为外键参考persons表中的id_p mysql> select * from perso ...

  2. PHP设置Redis key在当天有效|SCP对拷如何连接指定端口(非22端口)的远程主机

    $redis->set($key,$value); $expireTime = mktime(23, 59, 59, date("m"), date("d" ...

  3. 学习ThinkPHP5的第一天(安装 连接数据库)

    参考文档:thinkPHP5.0完全手册  一.安装 采用的是git安装方式: 应用项目:https://github.com/top-think/think 核心框架:https://github. ...

  4. 解决在 win10 下 vs2017 中创建 MFC 程序拖放文件接收不到 WM_DROPFILES 消息问题

    解决方案 这个问题是由于 win10 的安全机制搞的鬼,即使以管理员权限运行也不行,因为它会把 WM_DROPFILES 消息过滤掉,那怎么办呢?只需在窗口初始化 OnInitDialog() 里添加 ...

  5. 技巧-如何通过hive开发平台上传csv文件

    通过数据交换平台上传较大的文件时,经常会出现导入失败情况,换种方式通过新数据开发平台(stark)也可以轻松实现外部数据与hive的数据关联. --第一步.导入csv文件到hive --stark数据 ...

  6. STM32 HAL库学习系列第2篇 GPIO配置

    GPIO 库函数 基本就是使用以下几个函数 GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); void H ...

  7. SpringBoot 启动报The Java Virtual Machine has not been configured to use the desired default character encoding (UTF-8)

    解决方法: 启动的时候在VM中添加 Dfile.encoding=UTF-8 就好了!

  8. 20155223 2016-2017-2《Java程序设计》课程总结

    20155223 2016-2017-2<Java程序设计>课程总结 每周作业链接汇总 预备作业1 预备作业2 预备作业3 第一周 第二周 第三周 第四周 第五周 第六周 第七周 第八周 ...

  9. PostgreSQL的pg_stats学习

    磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面: PostgreSQL统计信息索引页     回到顶级页面:PostgreSQL索引页 对于pg_stas,说明文档在这里: http://w ...

  10. [arc063F]Snuke's Coloring 2-[线段树+观察]

    Description 传送门 Solution 我们先不考虑周长,只考虑长和宽. 依题意得答案下限为max(w+1,h+1),并且最后所得一定是个矩形(矩形内部无点). 好的,所以!!!答案一定会经 ...