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 }