/*求小数的组合数n<3000我们还是可以直接用杨辉三角搞定,但是如果超过3000的数,开个二维数组很不实际,故 我们要寻求一个直接的算法 这里要用到整数的拆分,快速幂模 以C(n,m)为例 C(n,m)=n!/((n-m)!*m!) 首先扰我们的要算比较大的数的阶乘了 我们可以先将n!用快速拆分法分为 2^x1*3^x2*5^x3*...*pi^xi(其中p为素数)方法见div函数。(证明有点难度- -!)先不在此证明了 拆分后对分式进行降幂运算x1[i]-=(x2[i]+x3[i]) 可以证明x1[i]>=0 证明:由于C(n,m)结果必然为整数,即n!%((n-m)!*m!)==0 所以n!为(n-m)!*m!的整数倍,即pi^x1i%(pi^x2i*pi^x3i)==0 即pi^(x1[i]-x2[i]-x3[i])为整数 x1[i]-x2[i]-x3[i]>=0 证毕 之后就是对 p[i]对x1[i]的幂模了(计算大幂的快速方法) */ #include<stdio.h> #include<string.h> #include<math.h> const int N = 1000001; const int M = 150000; int prm[M],np,p1[M],p2[M],p3[M],c = 20100501; bool is[N*2]; int getprm(int n)//素数打标 { int i,j,k = 0; int s,e = (int)(sqrt(0.0+n)+1); memset(is,1,sizeof(is)); prm[k++] = 2; is[0] = is[1] = 0; for(i=4;i<n;i+=2) is[i] = 0; for(i=3;i<e;i+=2) { if(is[i]) { prm[k++] = i; for(s=i*2,j=i*i;j<n;j+=s) is[j] = 0; } } for(; i<n; i+=2) { if(is[i]) prm[k++] = i; // } return k; } int div(int *arr,int n)//幂整数拆分(n!) { int i,tmp; for(i=0;i<np;i++) arr[i] = 0; for(i=0; i<np && n>=prm[i]; i++) { tmp = n; while(tmp) { arr[i] += tmp/prm[i]; tmp /= prm[i]; } } return i; } int b_pow(int *arr,int n)//快速幂模 { int i; long long res = 1,a,b,d; for(i=0;i<n;i++) { if(arr[i]) { a = prm[i]; b = arr[i]; d = 1; while(b) { if(b%2) d = (a*d)%c; a = (a*a)%c; b >>= 1; } res = (res*d)%c; } } return (int)res; } int C(int a,int b) { int len,i,r; len = div(p1,a); div(p2,a-b); div(p3,b); for(i=0;i<len;i++)//分母和分子的指数相减 p1[i] -= (p2[i]+p3[i]); return b_pow(p1,len); } int main() { int m,n,res; np = getprm(2000002); while(scanf("%d%d",&n,&m)) { res = C(n,m); printf("%d/n",res); } return 0; } //