#include <stdio.h> #include <string.h> #define MAX 102 int sim[1]={0}; int fac[210][MAX]={0}; void multiply(int s[],int max,int b) //大数乘法 { int i,ans=0; for (i=max;i>=0;i--) { ans+=s[i]*b; s[i]=ans%10000000;//一开始弄的是8个0 可能超出范围了,就弄了7个0 ans/=10000000; } } void div(int s[],int max,int b) //大数除法 { int i,ans=0; for (i=0;i<=max;i++) { ans=ans*10000000+s[i]; s[i]=ans/b; ans%=b; } } void getfac() //算阶乘 { int i; fac[0][MAX-1]=fac[1][MAX-1]=1; for (i=2;i<=200;i++) { memcpy(fac[i],fac[i-1],MAX*sizeof(int)); multiply(fac[i],MAX-1,i); } } void output1(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("%07d",s[i]); } printf("\n"); } int main() { int m,n,k=1; getfac(); while (scanf("%d%d",&m,&n),m+n) { if (n>m) { printf("Test #%d:\n0\n",k++); continue; } memcpy(sim,fac[m+n],(MAX)*sizeof(int)); multiply(sim,MAX-1,m-n+1); div(sim,MAX-1,m+1); output1(sim,k); k++; } return 0; }
如果有这么一个序列 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);
以上就是过程了 大数加递推
2015 7 11 重做
#include <iostream> #include <cstring> using namespace std; int main() { int i,j; int m,n; int ary[201],ans; int k=1,d; while (cin>>m>>n,m||n) { if (m<n) { cout<<"Test #"<<k++<<":"<<endl<<"0"<<endl; continue; } memset(ary,0,sizeof(ary)); ary[1] = 1; //fact(ary,m+n); for ( ans=0,i=2;i<=(m+n);i++) { for ( j=1;j<200;j ++) { ans +=ary[j] * i; ary[j] =ans%1000; ans /= 1000; } } d=(m-n+1); for ( j=1;j<200;j++) { ans +=ary[j] *d; ary[j] =ans%1000; ans /= 1000; } // cout<<d<<endl; //double dd=1/(m+1); ans=0; i=200; while(!ary[i]) i--; for (j=i;j>=1;j--) { ans =ans*1000 + ary[j]; ary[j] = ans/(m+1); ans %= (m+1); } cout<<"Test #"<<k++<<":"<<endl; i=200; while(!ary[i]) i--; cout<<ary[i--]; for (;i>=1;i--) { printf("%03d",ary[i]); } cout<<endl; } return 0; }