POJ 2429 GCD & LCM Inverse【miller-rabin算法+pollard rho 算法】

GCD & LCM Inverse
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 12952   Accepted: 2399

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

题意:

给出两个数的gcd 和lcm,让你求满足和最小的一对解


题解:

最直接的思路就肯定是进行素因子分解了,用到了pollard rho 算法(个人不懂),然后在这个算法的运行中,需要使用miller rabin 算法辅助........

使用这两个概率算法其实只是为了分解质因子,随后,进行dfs 枚举,求解满足条件的一对解


其实个人只是思路比较清楚一点,但是这两个算法还没有理解透彻,就不发表看法了....

直接使用的大神的模板...膜拜膜拜~~


这几天一直卡在这个算法的研究中,结果还是没理解清楚,不过还算是学到了点东西,比如:

1,大数的取模,为了防止中间过程溢出,可以用加法和移位来代替乘法,这一点在计算机组成原理里面刚好有涉及

2, 递归式的gcd 函数,不得不吐槽了,一般情况下确实很快,但是像这种数据比较大的情况下,竟然卡在了求gcd 的时间上(亲测递归TLE,迭代110MS AC)


一位学长说过:递归为人,迭代为神!


至于这两个概率算法,个人觉得如果如果不是专门搞研究方面的,倒不用太过于纠结,毕竟有概率失败的,如果你用去搞程序设计,在大数据的情况下,再小概率的事件都会发生,必定造成很多错误,一般来说,最主要的还应该是思维的锻炼和知识面的扩充,至少不至于对一些比较著名的方法和结论都不知道吧

好吧好吧,不扯了,个人的思想不是很成熟,大致发表一下自己的看法,需要学的东西还有很多,慢慢学吧!加油!


/*
http://blog.csdn.net/liuke19950717
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int S=20;
ll mult_mod(ll a,ll b,ll c)
{
    a%=c;b%=c;
    ll ret=0;
    while(b)
    {
        if(b&1)
		{
			ret+=a;ret%=c;
		}
        a<<=1;
        if(a>=c)
			a%=c;
        b>>=1;
    }
    return ret;
}

ll pow_mod(ll x,ll n,ll mod)
{
    if(n==1)return x%mod;
    x%=mod;
    ll tmp=x;
    ll ret=1;
    while(n)
    {
        if(n&1)
			ret=mult_mod(ret,tmp,mod);
        tmp=mult_mod(tmp,tmp,mod);
        n>>=1;
    }
    return ret;
}

bool check(ll a,ll n,ll x,ll t)
{
    ll ret=pow_mod(a,x,n);
    ll last=ret;
    for(int i=1;i<=t;i++)
    {
        ret=mult_mod(ret,ret,n);
        if(ret==1&&last!=1&&last!=n-1)
			return true;
        last=ret;
    }
    if(ret!=1)
		return true;
    return false;
}

bool Miller_Rabin(ll n)
{
    if(n<2)
		return false;
    if(n==2)
		return true;
    if((n&1)==0)
		return false;
    ll x=n-1;
    ll t=0;
    while((x&1)==0)
	{
		x>>=1;t++;
	}
    for(int i=0;i<S;i++)
    {
        ll a=rand()%(n-1)+1;
        if(check(a,n,x,t))
            return false;
    }
    return true;
}

ll factor[100];
int tol;

ll gcd(ll a,ll b)
{
    if(a==0)
		return 1;
    if(a<0)
		return gcd(-a,b);
    while(b)
    {
        ll t=a%b;
        a=b;b=t;
    }
    return a;
}
/*
// 递归 TLE!!!! 
ll gcd(l a,ll b)
{
	if(!b)
	{
		return a;
	}
	return gcd(b,a%b);
}
*/

ll Pollard_rho(ll x,ll c)
{
    ll i=1,k=2;
    ll x0=rand()%x;
    ll y=x0;
    while(1)
    {
        i++;
        x0=(mult_mod(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)
{
    if(Miller_Rabin(n))
    {
        factor[tol++]=n;
        return;
    }
    ll p=n;
    while(p>=n)
	{
		p=Pollard_rho(p,rand()%(n-1)+1);
	}
    findfac(p);
    findfac(n/p);
}

ll r[100];
int num;
ll k;

void dfs(ll now,int x,ll n)
{
    if(now>sqrt(n))
	{
		return;
	}
    k=max(k,now);
    for(int i=x;i<=num;i++)
	{
		dfs(now*r[i],i+1,n);
	}
}

int main()
{
    ll gcd,lcm,n;
    while(scanf("%lld%lld",&gcd,&lcm)!=EOF)
    {
        if(gcd==lcm)
        {
            printf("%lld %lld\n",gcd,lcm);
            continue;
        }
        tol=0;
        n=lcm/gcd;
        findfac(n);
		sort(factor,factor+tol);
        num=0;
		for(int i=0;i<=50;i++)
		{
			r[i]=1;
		}
        r[num]=factor[0];
        for(int i=1;i<tol;i++)
        {
            if(factor[i]==factor[i-1])
            {
            	r[num]=r[num]*factor[i];
			}
            else
            {
                num++;
                r[num]=factor[i];
            }
        }
        k=1;
		dfs(1,0,n);
        printf("%lld %lld\n",gcd*k,gcd*(n/k));
    }
    return 0;
}




你可能感兴趣的:(POJ 2429 GCD & LCM Inverse【miller-rabin算法+pollard rho 算法】)