hdu-1133

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1133

思路:有m个人拿50元的纸币,n个人拿100元的纸币门票价格是50元,要求每个售票员遇到100元时都能找回顾客50元。

(1)如果m<n就不行,ans=0;

(2)m>=n,总共有C(m+n,n)种可能,只要求出不符合要求的即可。

假如有一个m=3,n=2的序列01100,它不合法,将第二个1后的0变为1,1变为0,得到01111,显然它也不合法。

由此可以看出每一个(m,n)序列都能由(m-1,n+1)序列推过来,所以不合法的序列数总共有C(m+n,m+1)个

,总共合法的序列有C(m+n,n)- C(m+n,m+1)=  (m+n)!*(m-n+1)/(m+1)个。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int base = 10000;
const int maxn = 100;
int f[maxn*2][maxn*2],n,m,ans[maxn+20];
void mul(int a[],int x)
{
    int i,tmp=0;
    for(i=maxn-1;i>=0;i--)
    {
        tmp+=a[i]*x;
        a[i]=tmp%base;
        tmp/=base;
    }
}
void chu(int a[],int x)
{
    int i,tmp=0;
    for(i=0;i<=maxn;i++)
    {
        tmp=tmp*base+a[i];
        a[i]=tmp/x;
        tmp%=x;
    }
}
void Init()
{
    f[0][maxn-1]=f[1][maxn-1]=1;
    for(int i=2;i<=200;i++)
    {
        memcpy(f[i],f[i-1],maxn*sizeof(int));
        mul(f[i],i);
    }
}
int main(void)
{
    int i,j,pt=1;
    Init();
    while(~scanf("%d%d",&m,&n)&&(n+m))
    {
        printf("Test #%d:\n",pt++);
        if(n>m)
        {
            printf("0\n");
            continue;
        }
        memcpy(ans,f[n+m],maxn*sizeof(int));
        mul(ans,m-n+1);
        chu(ans,m+1);
        i=0;
        while(ans[i]==0) i++;
        printf("%d",ans[i++]);
        while(i<maxn) printf("%04d",ans[i++]);
        printf("\n");
    }
    return 0;
}

 

posted @ 2018-11-06 15:47  麟阁  阅读(176)  评论(0编辑  收藏  举报