Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 16973 | Accepted: 3137 |
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
题意:
给你两个数n和m,让你求出一组a和b满足
①a<=b;②Gcd(a, b) = n;③Lcm(a, b) = m;④a+b的和尽可能的小
思路:
m/n = Lcm(a, b)/Gcd(a, b) = a/Gcd(a, b)*b/Gcd(a, b)
也就是要找到一对a, b满足
①a和b互质
②a+b尽可能小
③a*b = n
很显然a和b一定都是m/n的若干个质因子的乘积
用Pollard_rho分解m/n的质因数,然后爆搜就行了,注意剪枝
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define LL long long
int t, cnt;
LL fat[101], val, ans, c, d;
LL Multi(LL a, LL b, LL mod)
{
LL ans = 0;
a %= mod;
while(b)
{
if(b%2==1) ans = (ans+a)%mod, b--;
else a = (a+a)%mod, b /= 2;
}
return ans;
}
LL Pow(LL a, LL b, LL mod)
{
LL ans = 1;
a %= mod;
while(b)
{
if(b&1) ans = Multi(ans, a, mod), b--;
else a = Multi(a, a, mod), b /= 2;
}
return ans;
}
LL Gcd(LL a, LL b)
{
if(b==0)
return a;
return Gcd(b, a%b);
}
int Miller_Rabin(LL n)
{
int i, j, k;
LL a, x, y, mod;
if(n==2) return 1;
if(n<2 || n%2==0) return 0;
k = 0, mod = n-1;
while(mod%2==0)
{
k++;
mod /= 2;
}
for(i=1;i<=10;i++)
{
a = rand()%(n-1)+1;
x = Pow(a, mod, n);
y = 0;
for(j=1;j<=k;j++)
{
y = Multi(x, x, n);
if(y==1 && x!=1 && x!=n-1)
return 0;
x = y;
}
if(y!=1)
return 0;
}
return 1;
}
LL Divi(LL n)
{
LL i, k, x, y, p, c;
if(n==1)
return 1;
k = 2, p = 1;
y = x = rand()%n, c = rand()%(n-1)+1;
for(i=1;p==1;i++)
{
x = (Multi(x, x, n)+c)%n;
p = x-y;
if(p<0)
p = -p;
p = Gcd(n, p);
if(i==k)
y = x, k *= 2;
}
return p;
}
void Pollard_rho(LL n)
{
LL p;
if(n==1)
return;
if(Miller_Rabin(n))
fat[++cnt] = n;
else
{
p = Divi(n);
Pollard_rho(n/p);
Pollard_rho(p);
}
}
void Sech(int x, LL now)
{
if(x>=cnt+1 || x>sqrt(val)+1)
return;
if(now+val/now<ans)
{
c = now;
d = val/now;
ans = now+val/now;
}
Sech(x+1, now*fat[x]);
Sech(x+1, now);
}
int main(void)
{
int i, k;
LL n, m, now;
while(scanf("%lld%lld", &n, &m)!=EOF)
{
k = cnt = 0;
val = m/n;
Pollard_rho(val);
sort(fat+1, fat+cnt+1);
for(i=1;i<=cnt;i++)
{
if(fat[i]!=fat[i-1])
{
if(i!=1)
fat[++k] = now;
now = fat[i];
}
else
now *= fat[i];
}
fat[++k] = now;
cnt = k;
ans = 1e18;
Sech(1, 1);
if(c>d)
swap(c, d);
printf("%lld %lld\n", c*n, d*n);
}
return 0;
}