【题目背景】
我们知道,一块泥坑里有一只佩奇和一只乔治,通过1+1=2,得到了这块泥坑里总共有两只猪的结论。
【题目描述】
求出C(n,r)的最后十位,其中0<r≤n≤30000,输出时不足十位数也按十位输出,此
时高位用0 表示。C(n,r)=n×(n-1)×……×(n-r+1)/(1×2×3×……×r)。
输入数据为两个以空格隔开的自然数n,r。
【输入】
一行两个整数
【输出】
一行,10 位数字
2
【样例输入】
5 2
【样例输出】
0000000010
问题分析:首先,连续r个自然数的积一定能够被r!整除,因为将式子展开,我们会发现r!(分母)中的每一项都会和分子中的某些数约分,最终分母便变成了1。因此,C(n,r)的值一定是一个自然数。
其次,本题是可以避免除法的,方法之一就是约分。 将分子分母中出现的质i分解成若干个质数的乘积,记录这若干个质数当中,每个数出现的次数(用数组),例如,把72分解成2*2*2*3*3,则a[2]=3,a[3]=2。3为2在72中的重数,2为3在72中的重数。然后,对于分母中出现了质因子,则a[质因子]--,若出现在分子中,则a[质因子]++最后,将每个质因子按其重数连乘即可。
#include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cstdlib> using namespace std; int a[30000],t,i,j,n,r,s; int b[21]; const int maxn=20; void divide(int n) { int m; m=2; while (m*m<=n) { while (n%m==0&&n!=0) { n=n/m; a[m]--;//m的重数个数减一 } m++; } a[n]--; } void times(int n) { int m; m=2; while (m*m<=n) { while(n%m==0&&n!=0) { n=n/m; a[m]++;//m的重数个数加1 } m++; } a[n]++; } void add(int d)//质因子与重数连乘 ,数组b储存结果的每一位数字 { int dd,i,t; i=1; j=0; while (i<=maxn) { t=b[i]*d+j; b[i]=t%10; j=t/10; i++; } i=1; j=0; while(i<=maxn) { t=b[i]+j; b[i]=t%10; j=t/10; i++; } } int main() { cin>>n>>r; memset(a,0,sizeof(a)); i=n-r+1; j=r; do { if (i<=n) { times(i); i++; } if (j>1) { divide(j); j--; } }while(i<=n||j>1); memset(b,0,sizeof(b)); b[1]=1; for (i=2;i<=29999;i++) { while (a[i]>0) { add(i); a[i]--; } } for (j=10; j>=1;j--)//输出组合数的末十位 cout<<b[j]; cout<<endl; return 0; }