FZU 1753

题目的思路还是很简单的,找出这些组合数中最大的公约数;

其中C(n,k)=n ! /k!/(n-k)!

所以枚举每个素因数,用(n!)的减去(k!)和(n-k)!的就行了...

最后取每组的最小值

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 
 5 using namespace std;
 6 const int maxn=100010;
 7 const int inf=0x3fffffff;
 8 int prime[maxn],num;
 9 bool isprime[maxn];
10 int cnt[maxn],lim;
11 typedef unsigned long long ll;
12 
13 void init()
14 {
15     for(int i=2; i<maxn; i++)
16         if(!isprime[i])
17         {
18             prime[num++]=i;
19             for(int j=2*i; j<maxn; j+=i)
20                 isprime[j]=1;
21         }
22 }
23 
24 void cal(int a,int b,int c)
25 {
26     int nn=-1;
27     for(int i=0; prime[i]<=lim; i++)
28     {
29         int t=0,pre=a;
30         if(pre>=prime[i]) while(pre) t+=pre/prime[i],pre/=prime[i];
31         pre=b;
32         if(pre>=prime[i]) while(pre) t-=pre/prime[i],pre/=prime[i];
33         pre=c;
34         if(pre>=prime[i]) while(pre) t-=pre/prime[i],pre/=prime[i];
35         if(cnt[i]==-1||cnt[i]>t) cnt[i]=t;
36         if(cnt[i]) nn=prime[i];
37     }
38     lim=nn;
39 }
40 ll pow1(ll a,int n)
41 {
42     ll ret=1;
43     for(; n; n>>=1,a=a*a)
44         if(n&1) ret*=a;
45     return ret;
46 }
47 int main()
48 {
49     init();
50     int n,a[150],b[150];
51     while(scanf("%d",&n)==1)
52     {
53         lim=inf;
54         for(int i=0; i<n; i++)
55         {
56             scanf("%d %d",&a[i],&b[i]);
57             lim=min(lim,a[i]);
58         }
59         memset(cnt,-1,sizeof(cnt));
60         for(int i=0; i<n; i++)
61             cal(a[i],b[i],a[i]-b[i]);
62         ll ans=1;
63         for(int i=0; prime[i]<=lim; i++)
64             if(cnt[i]>0) ans*=pow1(prime[i],cnt[i]);
65         printf("%I64u\n",ans);
66     }
67     return 0;
68 }
View Code

 

posted @ 2013-08-26 13:11  Yours1103  阅读(173)  评论(0编辑  收藏  举报