洛谷P2406 最小和

已知 a,b 是正整数且 a ≤ b。

求满足条件且 x + y 的值最小的 x,y。

条件:

  • gcd(x,y) = a
  • lcm(x,y) = b
  •  x ≤ y

输入格式

多组数据,EOF 判断结束

共有不超过 10^{3} 行,每行两个数 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 < 2^{^{63}}

EOF 结束,没有代表行数的 n,第一行就是数据。

数据随机生成。

题解:

因为 gcd(x,y) = a,即 x,y 中都含有 a 这个因数,所以不妨先将 a 从 x,y 中分离出来,到最后求出解后再把 a 乘回去。


因此,问题就转化成了求一对互质的整数 x,y, 使 x * y = b / a,只要对 b / a 分解质因数,把 b / a 根据数论定理表示成若干个不同质数的幂的乘积,即 p_{1}{_{}}^{k_{1}} * p_{2}{_{}}^{k_{2}} * p_{3}{_{}}^{k_{3}} * ...... * p_{m}{_{}}^{k_{m}}

然后从小到大枚举 x 的值,让 x = p{_{1}}^{k_{1}}, p{_{1}}^{k_{1}} * p{_{2}}^{k_{2}}, p{_{1}}^{k_{1}} * p{_{2}}^{k_{2}} * p{_{3}}^{k_{3}}, ......,, y = (b / a) / x, 这样能保证 gcd(x,y) 始终为1(x,y没有公共的质因子,p_{1},p_{2}等质数都是不相同的)

在枚举过程中用一个变量记录下 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;
	}
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值