您的位置:首页 > 其它

fzu 1753 Another Easy Problem

2012-09-04 15:52 316 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: