[HDU] 1133-Buy the Ticket

在这里插入图片描述
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1133

n:50元个数
m:100元个数

一看到这个题目我就顺着思路写了,先找出不同种排法再*n!*m!用BigInteger保存结果,最后超时。在捣鼓了很久之后在网上看到了首次接触的Catalan数,通过递推就很容易得到答案。
Cataland的一些详细介绍:http://daybreakcx.is-programmer.com/posts/17315.html

这里有一个很有意思的解法:

合法的序列 = 总序列 - 不合法的序列。总的序列是:C(m+n, n),而不合法的序列,假设最早买不到票的人为k,那么他必然是手持100元而且售票口没有钱,出现这种情况有两种可能,一种是他是第一个买票的;第二种是在他前面即买票的手持50和100元的人数相同。

即假设设手持50的为0,手持100的为1,让他们排成一排,则不合法的序列中必然能找得到第一个买不到票的人k,例如:01 1 01010,k = 2。这时候,将0-k的1置换成0,将0置换成1,就会出现序列中出现0的个数为n+1,1的个数为m-1,上面的通过置换后变成:10001010。也就是说,不合法的序列的个数为:C(m+n, n+1)。

所以得到公式:
Total = (C(m+n, n)-C(m+n, n+1))*m!*n!,化简得:(m+n)! * (n-m+1)/(n+1)

package com.HDU;

import java.math.BigInteger;
import java.util.Scanner;

public class Ticket2 {
	public static void main(String[] args) {
		
		Scanner in = new Scanner(System.in);
		int n,m;
		int count = 1;
		while(in.hasNext()) {
			
			n = in.nextInt();
			
			m = in.nextInt();
			
			if(n==0 && m==0)
				break;
			
			BigInteger ans = BigInteger.ONE;
			
			if(n<m) ans = BigInteger.ZERO;
			//(m+n)!
			for(int i = 1;i<=n+m;i++)
				ans=ans.multiply(BigInteger.valueOf(i));
			
			int mpl = n-m+1;
			int dvd = n+1;
			
			ans = ans.multiply(BigInteger.valueOf(mpl));
			ans = ans.divide(BigInteger.valueOf(dvd));
			
			System.out.println("Test #"+count+":");
			System.out.println(ans);
			
			
		}

		
		
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值