已知 a,b 是正整数且 a ≤ b。
求满足条件且 x + y 的值最小的 x,y。
条件:
- gcd(x,y) = a
- lcm(x,y) = b
- x ≤ y
输入格式
多组数据,EOF 判断结束
共有不超过 行,每行两个数 a,b。
输出格式
输出和输入文件一样多的行,每行一个半角空格隔开的两个数 x,y。
输入输出样例
输入 #1
3 60
输出 #1
12 15
输入 #2
200 20000 300 30000 400 40000
输出 #2
800 5000 1200 7500 1600 10000
说明/提示:
3 ≤ a, b <
EOF 结束,没有代表行数的 n,第一行就是数据。
数据随机生成。
题解:
因为 gcd(x,y) = a,即 x,y 中都含有 a 这个因数,所以不妨先将 a 从 x,y 中分离出来,到最后求出解后再把 a 乘回去。
因此,问题就转化成了求一对互质的整数 x,y, 使 x * y = b / a,只要对 b / a 分解质因数,把 b / a 根据数论定理表示成若干个不同质数的幂的乘积,即
然后从小到大枚举 x 的值,让 x = , y = (b / a) / x, 这样能保证 gcd(x,y) 始终为1(x,y没有公共的质因子,
等质数都是不相同的)
在枚举过程中用一个变量记录下 x − y 的最小值(乘积一定,两数差越小,和越小)
如果当前值比最小值更小则更新答案,枚举结束后要判断一下,如果 x > y 则交换 x, y, 最后给 x, y都乘上 a 即可。
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main() {
int a, b;
unordered_map<int, int> primes;
while (cin >> a >> b) {
int x = 0, y = 0;
int tot = b / a;
int m = tot;
primes.clear();
for (int i = 2; i <= m / i; i++)
while (m % i == 0) {
m /= i;
primes[i] ++;
}
if (m > 1) primes[m] ++;
int minn = b / a - 1;
for (auto p : primes) {
int aa = p.first, bb = p.second;
int ans = pow(p.first, p.second);
int tmp = abs(ans - tot / ans);
if (tmp < minn) minn = tmp, x = ans, y = tot / ans;
}
if (x <= y) cout << x * a << " " << y * a << endl;
else cout << y * a << " " << x * a << endl;
}
}