传送门:http://poj.org/problem?id=2429
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
题意
已知 gcd(a,b),lcm(a,b),求解 使a+b的值 最小的 a,b;
思路
令:g = gcd(a,b);l = lcm(a,b);
则
l
g
{{l} \over {g}}
gl =
a
g
{{a} \over {g}}
ga *
b
g
{{b} \over {g}}
gb,很明显
a
g
{{a} \over {g}}
ga ,
b
g
{{b} \over {g}}
gb是互质的,所以搜索
l
g
{{l} \over {g}}
gl 的所有质因子组成的数,找寻和最小的那一对(m,n),然后输出(mg,ng)即可。
注意这里找寻的是所有质因子,所以某种质因子可能有多个,又因为保证
a
g
{{a} \over {g}}
ga ,
b
g
{{b} \over {g}}
gb互质,所以就把相同的质因子合并(相乘)
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
#include<ctime>
#define ll long long
#define ld long double
#define ull unsigned long long
using namespace std;
const int maxn = 1000010;
const ll lnf = 0x3f3f3f3f3f3f3f;
int t,tot;
ll a[] = {2,3,5,7,11,61,13,17};
ll g,l,p,ans[maxn];
int nmb[maxn];
ll fl1,fl2,_min;
ll mul(ll x,ll y,ll z)
{
ll sm=(ld)x/z*y;
return ((ull)x*y-(ull)sm*z+z)%z;
}
ll ksm(ll x,ll y,ll z)
{
ll ans=1;
x %= z;
for(ll i=y;i;i>>=1){
if(i&1) ans=mul(ans,x,z);
x=mul(x,x,z);
}
return ans%z;
}
ll gcd(ll x,ll y)
{
return y==0 ? x : gcd(y,x%y);
}
bool rabin(ll x,ll y)
{
if(ksm(x,y-1,y)!=1)
return 0;
ll z=y-1,sm;
while(!(z&1)){
z>>=1;
sm=ksm(x,z,y);
if(sm!=1&&sm!=y-1) return 0;
if(sm==y-1) return 1;
}
return 1;
}
bool miller(ll x)
{
bool ans = true;
for(int i=0;i<8;i++){
if(a[i]==x) return 1;
ans &= rabin(a[i],x);
}
return ans;
}
ll Pollard(ll x)
{
ll a,b,d,g,y,i,j;
while(1){
a = b = rand()%x;
g = rand()%x;
y=1;i=0;j=1;
while(++i){
a = (mul(a,a,x)+g) % x;
if(a>b) y = mul(y,a-b,x);
else y = mul(y,b-a,x);
if(a==b||!y) break;
if(i<127||i==j){
d=gcd(x,y);
if(d>1&&d!=x) return d;
if(i==j){
b=a;
j<<=1;
}
}
}
}
}
void Find(ll x)
{
if(x<=1) return ;
if(miller(x)){
ans[tot++] = x;
return;
}
ll y=Pollard(x);
if(x%y==0) x/=y; //这里找寻的是所有质因子,
//while(x%y==0) x/=y; //找寻种类
Find(y);Find(x);
}
void DFS(int pos,ll a,ll b)
{
if(pos>=tot){
if(a+b<_min){
_min = a+b;
fl1 = a;
fl2 = b;
}
return ;
}
DFS(pos+1,a*ans[pos],b);
DFS(pos+1,a,b*ans[pos]);
}
int main()
{
ll pp;
int cnt;
while(~scanf("%lld%lld",&g,&l)){
if(g==l){ //特判
printf("%lld %lld\n",g,l);
continue;
}
p = l/g;
tot = 0;
Find(p);
sort(ans,ans+tot);
int j = 0;
for(int i=0;i<tot;i++){ //相同的质因子合并
ll tmp = ans[i];
while(i+1<tot&&ans[i]==ans[i+1]){
tmp *= ans[i];
i++;
}
ans[j++] = tmp;
}
tot = j;
_min = lnf;
DFS(0,1,1); //搜索
if(fl1>fl2) swap(fl1,fl2);
printf("%lld %lld\n",fl1*g,fl2*g);
}
return 0;
}