fzu 1753 Another Easy Problem
这个题目是不错的题目,求最大公约数的时候要求用素因子分解,不然会溢出(其实答案本身都可能溢出,只不过数据保证在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; }