题意:求T组组合数C(n,m)的最大公约数。(1<=m<=n<=100000)
思路:求出每组组合数的公共素因子,相乘。对于一个数n,从1到n有多少个数包含一个素因子p呢?答案:n/p个,两个p呢,n/p/p个。
所以,求N!里包含某素数因子p的个数,就可以这样求。
1 while(n>0){
2 x+=n/p;
3 n/=p;
4 }
题目链接:http://acm.fzu.edu.cn/problem.php?pid=1753
View Code
1 #include <cstdio> 2 #include <cmath> 3 #include <cstdlib> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 const int N=100010; 10 11 bool isprime[N]; 12 int prime[N],num[N],p[N]; 13 int n[200],m[200],cnt; 14 15 void getprime(){ 16 cnt=0; 17 for(int i=2;i<N;i++) 18 if(!isprime[i]){ 19 prime[++cnt]=i; 20 for(int j=2;i*j<N;j++) 21 isprime[i*j]=true; 22 } 23 } 24 25 int main(){ 26 27 // freopen("data.in","r",stdin); 28 // freopen("data.out","w",stdout); 29 30 int t,Min,a,b,k,i,j; 31 getprime(); 32 while(scanf("%d",&t)!=EOF){ 33 Min=N; 34 for(i=0;i<t;i++){ 35 scanf("%d%d",&n[i],&m[i]); 36 if(Min>n[i]) Min=n[i]; 37 } 38 memset(num,-1,sizeof(num)); 39 while(t--){ 40 a=n[t]; 41 b=m[t]; 42 memset(p,0,sizeof(p)); 43 for(i=1;i<=cnt&&prime[i]<=Min&&prime[i]<=a;i++){ 44 k=a; 45 while(k>0){ 46 p[prime[i]]+=k/prime[i]; 47 k/=prime[i]; 48 } 49 } 50 for(i=1;i<=cnt&&prime[i]<=Min&&prime[i]<=b;i++){ 51 k=b; 52 while(k>0){ 53 p[prime[i]]-=k/prime[i]; 54 k/=prime[i]; 55 } 56 } 57 for(i=1;i<=cnt&&prime[i]<=Min&&prime[i]<=a-b;i++){ 58 k=a-b; 59 while(k>0){ 60 p[prime[i]]-=k/prime[i]; 61 k/=prime[i]; 62 } 63 } 64 for(i=1;i<=cnt;i++){ 65 if(num[prime[i]]==-1) num[prime[i]]=p[prime[i]]; 66 else if(num[prime[i]]>p[prime[i]]) num[prime[i]]=p[prime[i]]; 67 } 68 } 69 __int64 ans=1; 70 for(i=1;i<=cnt;i++){ 71 if(num[prime[i]]>0) 72 for(j=0;j<num[prime[i]];j++) 73 ans*=prime[i]; 74 } 75 printf("%I64d\n",ans); 76 } 77 return 0; 78 }