满足条件的排列,为【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;
}