zoukankan      html  css  js  c++  java
  • hdu 1133

    转帖自  http://xuyemin520.is-programmer.com/posts/26317.html

    还有  http://hi.baidu.com/a363310925/blog/item/aced542d719b2b5d4fc22695.html

    题意:M+N个人排队买票,票的单价是50¥,每个人只能买一张。 M个人拿50的去买,N个人拿100的去买,然后悲剧的是售票处开始的时候没有钱,所以如果拿100块买票人前面的拿50块买票的人小于或者等于用100块买票的人,这种排队方式就不合法,也就是不能顺利全部都买到票(因为没零钱找了)!

    卡特兰数的应用

    该题的公式:(C(m+n, n)-C(m+n, m+1))*m!*n! 化简即(m+n)!*(m-n+1)/(m+1)

    m个人拿50n个人拿100 所以如果 n>m,那么排序方法数为 0 这一点很容易想清楚

    现在我们假设 50的人用 ‘0’表示, 100的人用 1 表示。

    如果有这么一个序列 0101101001001111..........
    当第K个位置出现1的个数多余0的个数时就是一个不合法序列了
    假设n=4 n=3的一个序列是:0110100 显然,它不合法, 现在我们把它稍微变化一下:
    把第二个1(这个1前面的都是合法的)后面的所有位0变成11变成0
    就得到 0111011 这个序列1的数量多于0的数量, 显然不合法, 但现在的关键不是看这个序列是不是合法的
    关键是:它和我们的不合法序列 0110100 成一一对应的关系
    也就是说任意一个不合法序列(m0n1) 都可以由另外一个序列(n-10m+11)得到
    另外我们知道,一个序列要么是合法的,要么是不合法的
    所以,合法序列数量 = 序列总数量 - 不合法序列的总量
    序列总数可以这样计算m+n 个位置中, 选择 n 个位置出来填上 1 所以是 C(m+n, n)
    不合法序列的数量就是: m+n 个位置中, 选择 m+1 个位置出来填上 1 所以是 C(m+n, m+1)
    然后每个人都是不一样的,所以需要全排列 m! * n!

    题目还涉及到了大数乘小数,还有大数除小数

    #include<iostream>
    #include<cstdio>
    #include<cstring> 
    #define MAX 201
    using namespace std;
    int factor[205][MAX]={0}; 
    int sim[201]={0};
    int multiply(int s[],int Max,int b)
    {
    	int ans=0,i;   
    	for(i=Max;i>=1;i--)
    	{        
    		ans+=s[i]*b;    
    		s[i]=ans%10000;  
    		ans=ans/10000;  
    	}   
    	return 0;
    } 
    int div(int s[],int Max,int b)
    {  
    	int ans=0,t,i;  
    	for(i=1;i<=Max;i++)
    	{       
    		t=ans*10000+s[i];   
    		s[i]=t/b;    
    		ans=t%b;  
    	}   
    	return 0;
    } 
    int getfactor()
    {  
    	int i;   
    	factor[0][MAX-1]=factor[1][MAX-1]=1; 
    	for(i=2;i<=203;i++)
    	{       
    		memcpy(factor[i],factor[i-1],MAX*sizeof(int));
    		multiply(factor[i],MAX-1,i);  
    	}    
    	return 0;
    } 
    int output(int *s,int k)
    {    
    	int i=1;    
    	printf("Test #%d:\n",k);  
    	while(s[i]==0&&i<MAX)  
    		i++;  
    	printf("%d",s[i++]);  
    	for(;i<MAX;i++)    
    		printf("%04d",s[i]);   
    	printf("\n");   
    	return 0;
    }
    int main()
    {  
    	int m,n,i,k=1; 
    	getfactor(); 
    	while(scanf("%d %d",&m,&n),m+n)
    	{        
    		memcpy(sim,factor[m+n],sizeof(int)*MAX);   
    		if(n>m){  
    			printf("Test #%d:\n",k++);
    			printf("0\n");                         //别忘记了 判断这种情况,   
    			continue;     
    		}      
    		multiply(sim,MAX-1,m-n+1);    
    		div(sim,MAX-1,m+1);     
    		output(sim,k);     
    		k++;    
    	}   
    	return 0;
    }
    


  • 相关阅读:
    TextBox 只有下划线
    can't find web control library(web控件库)
    DropDownListSalesAC”有一个无效 SelectedValue,因为它不在项目列表中。
    IDE、SATA、SCSI、SAS、FC、SSD 硬盘类型
    如何打印1px表格
    CSS控制打印 分页
    Virtual Server could not open its emulated Ethernet switch driver. To fix this problem, reenable the Virtual Server Emulated Et
    Xml中SelectSingleNode方法中的xpath用法
    热带水果莫入冰箱?水果存放冰箱大法
    探索Asp.net的Postback机制
  • 原文地址:https://www.cnblogs.com/nanke/p/2171891.html
Copyright © 2011-2022 走看看