这个题目是不错的题目,求最大公约数的时候要求用素因子分解,不然会溢出(其实答案本身都可能溢出,只不过数据保证在long long的表示范围内)
C(a,b) = a! / (b! * (a-b)! )
素因子分解 有个优化就是枚举每个素因子,而不是枚举先枚举n!的每个数,然后在素因子分解
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=100010;
const int inf=0x3fffffff;
int prime[maxn],num;
bool isprime[maxn];
int cnt[maxn],lim;
typedef unsigned long long ll;
void init()
{
for(int i=2;i<maxn;i++)
if(!isprime[i])
{
prime[num++]=i;
for(int j=2*i;j<maxn;j+=i)
isprime[j]=1;
}
}
void cal(int a,int b,int c)
{
int nn=-1;
for(int i=0;prime[i]<=lim;i++)
{
int t=0,pre=a;
if(pre>=prime[i]) while(pre) t+=pre/prime[i],pre/=prime[i];
pre=b;
if(pre>=prime[i]) while(pre) t-=pre/prime[i],pre/=prime[i];
pre=c;
if(pre>=prime[i]) while(pre) t-=pre/prime[i],pre/=prime[i];
if(cnt[i]==-1||cnt[i]>t) cnt[i]=t;
if(cnt[i]) nn=prime[i];
}
lim=nn;
}
ll pow1(ll a,int n)
{
ll ret=1;
for(;n;n>>=1,a=a*a)
if(n&1) ret*=a;
return ret;
}
int main()
{
init();
int n,a[150],b[150];
while(scanf("%d",&n)==1)
{
lim=inf;
for(int i=0;i<n;i++) scanf("%d %d",&a[i],&b[i]),lim=min(lim,a[i]);
memset(cnt,-1,sizeof(cnt));
for(int i=0;i<n;i++)
cal(a[i],b[i],a[i]-b[i]);
ll ans=1;
for(int i=0;prime[i]<=lim;i++)
if(cnt[i]>0) ans*=pow1(prime[i],cnt[i]);
printf("%I64u\n",ans);
}
return 0;
}