POJ 2429 GCD & LCM Inverse(素数判定Miller-Rabin+素因子分解Pollard-rho+二进制枚举)

GCD & LCM Inverse

Time Limit: 2000MS

 

Memory Limit: 65536K

Total Submissions: 18825

 

Accepted: 3486

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(a,b)lcm(a,b),求ab,如果存在多组方案则输出a+b最小的那一组
分析:
首先,我们可以看出(x/gcd)*(y/gcd)=lcm/gcd,并且x/gcdy/gcd互质,那么我们先利用把所有的质数求出来Pollard_Rho,将相同的质数合并,现在的问题转变成把合并后的质数分为两堆,使得x+y最小,然后我们可以采用二进制枚举(解释点这里),一个个枚举出来。

代码实现:

#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
using namespace std;
 
 
//****************************************************************
// Miller_Rabin 算法进行素数测试
//速度快,而且可以判断 <2^63的数
//****************************************************************
const int S=20;//随机算法判定次数,S越大,判错概率越小
 
typedef long long ll;
//计算 (a*b)%c.   a,b都是long long的数,直接相乘可能溢出的
//  a,b,c <2^63
long long mult_mod(long long a,long long b,long long c)       //快速乘计算   (a*b)%c
{
    a%=c;
    b%=c;
    long long ret=0;
    while(b)
    {
        if(b&1){ret+=a;ret%=c;}
        a<<=1;
        if(a>=c)a%=c;
        b>>=1;
    }
    return ret;
}
 
 
 
//计算  x^n %c  把快速幂分成这两部分写的好处,可以防止数越界
long long pow_mod(long long x,long long n,long long mod)//快速幂 计算  x^n%c
{
    if(n==1)return x%mod;
    x%=mod;
    long long tmp=x;
    long long ret=1;
    while(n)
    {
        if(n&1) ret=mult_mod(ret,tmp,mod);
        tmp=mult_mod(tmp,tmp,mod);
        n>>=1;
    }
    return ret;
}
 
 
 
 
 
//以a为基,n-1=x*2^t      a^(n-1)=1(mod n)  验证n是不是合数
//一定是合数返回true,不一定返回false
bool check(long long a,long long n,long long x,long long t)
{
    long long ret=pow_mod(a,x,n);
    long long 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;
}
 
// Miller_Rabin()算法素数判定
//是素数返回true.(可能是伪素数,但概率极小)
//合数返回false;
 
bool Miller_Rabin(long long n)
{
    if(n<2)return false;
    if(n==2)return true;
    if((n&1)==0) return false;//偶数
    long long x=n-1;
    long long t=0;
    while((x&1)==0){x>>=1;t++;}
    for(int i=0;i=n)p=Pollard_rho(p,rand()%(n-1)+1);
    findfac(p);
    findfac(n/p);
}
 
int main()
{
    //srand(time(NULL));//需要time.h头文件//POJ上G++不能加这句话
    long long g,lcm;
    while(scanf("%I64d%I64d",&g,&lcm)!=EOF)
    {
    	 if (g == lcm)
        {
            printf("%lld %lld\n",g,lcm);
            continue;
        }

		ll ans=lcm/g;
        tol=0; 
        findfac(ans);
      
       
		sort (factor, factor + tol); //fac保存的是ans的素因子,比如3 60对应的fac数组是2 2 5
 
       int  k = 0;
        x[0] = factor[0];
        for (int i =1; itx+ty)
                n=tx+ty,a=tx,b=ty;
            
        }
            
      printf("%lld %lld\n",a*g,b*g);;
       
       
    }
    return 0;
}

 

你可能感兴趣的:(2018暑假ACM集训,数学----数论)