[POJ 2429] GCD & LCM Inverse

GCD & LCM Inverse
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 10621   Accepted: 1939

Description

Given two positive integers a and b, we can easily calculate the greatest common divisor (GCD) and the least common multiple (LCM) of a and b. But what about the inverse? That is: given GCD and LCM, finding a and b.

Input

The input contains multiple test cases, each of which contains two positive integers, the GCD and the LCM. You can assume that these two numbers are both less than 2^63.

Output

For each test case, output a and b in ascending order. If there are multiple solutions, output the pair with smallest a + b.

Sample Input

3 60

Sample Output

12 15

Source

POJ Achilles
 
#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <algorithm>

#include <cmath>

#include <ctime>

using namespace std;

#define INF 0x3f3f3f3f3f3f3f3f

#define ll long long

#define S 8



ll mult(ll a,ll b,ll mod)

{

    a%=mod,b%=mod;

    ll ret=0;

    while(b)

    {

        if(b&1)

        {

            ret+=a;

            if(ret>=mod) ret-=mod;

        }

        a<<=1;

        if(a>=mod) a-=mod;

        b>>=1;

    }

    return ret;

}

ll pow(ll a,ll n,ll mod)

{

    a=a%mod;

    ll ret=1;

    while(n)

    {

        if(n&1) ret=mult(ret,a,mod);

        a=mult(a,a,mod);

        n>>=1;

    }

    return ret;

}

bool check(ll a,ll n,ll x,ll t)

{

    ll ret=pow(a,x,n),last=ret;

    for(int i=1;i<=t;i++)

    {

        ret=mult(ret,ret,n);

        if(ret==1 && last!=1 && last!=n-1) return 1;

        last=ret;

    }

    if(ret!=1) return 1;

    return 0;

}

bool Miller_Rabin(ll n)

{

    if(n<2) return 0;

    if(n==2) return 1;

    if((n&1)==0) return 0;

    ll x=n-1,t=0;

    while((x&1)==0) { x>>=1;t++;}

    srand(time(NULL));

    for(int i=0;i<S;i++)

    {

        ll a=rand()%(n-1)+1;

        if(check(a,n,x,t)) return 0;

    }

    return 1;

}

int tot;

ll factor[1000];

ll gcd(ll a,ll b)

{

    ll t;

    while(b)

    {

        t=a;

        a=b;

        b=t%b;

    }

    if(a>=0) return a;

    return -a;

}

ll pollard_rho(ll x,ll c)

{

    ll i=1,k=2;

    srand(time(NULL));

    ll x0=rand()%(x-1)+1;

    ll y=x0;

    while(1)

    {

        i++;

        x0=(mult(x0,x0,x)+c)%x;

        ll d=gcd(y-x0,x);

        if(d!=1 && d!=x) return d;

        if(y==x0) return x;

        if(i==k) y=x0,k+=k;

    }

}

void FindFac(ll n,int k=107)

{

    if(n==1) return;

    if(Miller_Rabin(n))

    {

        factor[tot++]=n;

        return;

    }

    ll p=n;

    int c=k;

    while(p>=n) p=pollard_rho(p,c--);

    FindFac(p,k);

    FindFac(n/p,k);

}

ll ansx,ansy,ans;

void dfs(int k,ll x,ll y)

{

    if(k>=tot)

    {

        if(x+y<ans)

        {

            ans=x+y;

            ansx=x;

            ansy=y;

        }

        return;

    }

    dfs(k+1,x*factor[k],y);

    dfs(k+1,x,y*factor[k]);

}

int main()

{

    int i,j;

    ll n,m;

    while(scanf("%lld%lld",&m,&n)!=EOF)

    {

        tot=0;

        ans=INF;  //注意初始化

        FindFac(n/m,107);

        sort(factor,factor+tot);

        for(i=j=0;i<tot;i++)

        {

            ll tmp=factor[i];

            while(i+1<tot && factor[i]==factor[i+1]) //注意边界

            {

                tmp*=factor[i];

                i++;

            }

            factor[j++]=tmp;

        }

        tot=j;

        dfs(0,1,1);

        if(ansx>ansy) swap(ansx,ansy);

        printf("%lld %lld\n",ansx*m,ansy*m);

    }

    return 0;

}

 

你可能感兴趣的:(inverse)