hdu-1133

来源:互联网 发布:androidstudio源码网 编辑:程序博客网 时间:2024/05/21 10:21
解题思路(转):( C(m+n, n) - C(m+n, m+1) ) * m! * n! 化简即 (m+n)! * (m-n+1) / (m+1)

推導過程如下:

m個人拿50,n個人拿100

1、如果n > m,那麼排序方法數為0,這一點很容易想清楚
2、現在我們假設拿50的人用‘0’表示,拿100的人用‘1’表示。
如果有這麼一個序列0101101001001111。
當第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)得到。
另外我們知道,一个序列要麼是合法的,要麼是不合法的
所以,合法序列數量 = 序列總數量 - 不合法序列的總量
序列總數可以這樣計算 m+n個位置中,選擇n個位置出來填上1,所以是C(m+n,n).
不合法序列的數量就是: m+n個位置中,選擇m+1個位置出來填上1,所以是C(m+n,m+1).
然後每個人都是不一樣的,所以需要全排列m! * n!.
所以最後的公式為:( C(m+n,n) - C(m+n,m+1) ) * m! * n!
化簡即為:(m+n)!*(m-n+1)/(m+1)
代码:
#include<stdio.h>#include<string.h>#define N 222#define maxx 102#define base 10000void multiply(int *a,int b){int i,t=0;for(i=maxx-1;i>=0;--i){t+=a[i]*b;a[i]=t%base;t/=base;}}void divide(int *a,int b){int i,div=0;for(i=0;i<maxx;++i){div=div*base+a[i];a[i]=div/b;div%=b;}}int f[N][maxx];void jiecheng(){int i;f[0][maxx-1]=f[1][maxx-1]=1;for(i=2;i<N;++i){memcpy(f[i],f[i-1],maxx*sizeof(int));multiply(f[i],i);}}void print(int *a){int i=0;while(i<maxx && a[i]==0)i++;printf("%d",a[i++]);while(i<maxx)printf("%04d",a[i++]);printf("\n");}int main(){//freopen("d:\\test.txt","r",stdin);int i,j,k;int m,n;int t=1;int a[maxx];jiecheng();while(scanf("%d%d",&m,&n),m+n){printf("Test #%d:\n",t++);if(n>m){printf("0\n");continue;}memcpy(a,f[m+n],maxx*sizeof(int));multiply(a,m-n+1);divide(a,m+1);print(a);}return 0;}

  

原创粉丝点击