Buy the Ticket

满足条件的排列,为【C(M+N,N)-C(M+N,M+1)】*M*,既所有的情况为C(M+N,N)*M*N;而每个不满足的排序,当第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)得到 (来自
BlackRose的空间

#include<stdio.h>

#include<string.h>
int a[220][401],len[220];
#define N 200
void factorial()
{  int i,l1,r=0,temp;
   memset(a,0,sizeof(a));    /*n阶乘*/
   a[1][0]=1;len[1]=1;
   for(i=2;i<=N;i++)
   {  
  for(l1=0;l1<len[i-1];l1++)
     a[i][l1]+=a[i-1][l1]*i;
       for(l1=0;l1<len[i-1];l1++)
  {   temp=a[i][l1]+r;
  a[i][l1]=temp%10;
  r=temp/10;
  }
  len[i]=len[i-1];
  while(r)
  {  
 a[i][len[i]++]=r%10;
     r/=10;
  }
   }
}
int main()                           /*公式(m+n)!*(m-n+1)/m+1*/
{  int n,m,i,b[500],s,s1,s2,s3,count=0,r,temp,l;
   factorial();
   while(scanf("%d%d",&m,&n)==2)
   {  
 if(!m&&!n)
         break;
 count++;
      if(n>m)
 { printf("Test #%d:\n0\n",count);
   continue;
 }
 s=m+n;
      s1=m-n+1;
 s2=m+1;
 memset(b,0,sizeof(b));
 l=len[s];
      for(i=0,r=0;i<l;i++)           /*大乘小*/
 {  temp=a[s][i]*s1+r;
    b[i]=temp%10;
r=temp/10;
 }          
      while(r)
 { b[l++]=r%10;
   r/=10;
 }
 s3=0;
      for(i=l-1,r=0;i>=0;i--)
 {  
 s3=b[i]+r*10;
 b[i]=s3/s2;
 r=s3%s2;
 }         /*大除小*/
 while(b[l]==0)
 l--;
 printf("Test #%d:\n",count);
 for(i=l;i>=0;i--)
        printf("%d",b[i]);
 printf("\n");
   }
   return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值