Neko does Maths

Neko does Maths

Created by LXC on Sat Jul 22 16:00:33 2023

https://codeforces.com/problemset/problem/1152/C

ranting: 1800

tag: brute force, math, number theory

problem

给出非负整数a和b,求非负整数k使得a+k和b+k的最小公倍数最小,如果有多个k,求最小的k。

$a,b\le 10^9$

solution

我们知道lcm(a,b) = a*b/gcd(a,b)

不妨设a < b,那么gcd(a,b)=gcd(a,b-a)

所以gcd(a+k,b+k) = gcd(a+k,b-a)

gcd(a+k, b-a)的值只可能是b-a的因子。

枚举b-a的所有因子x,a+k必须为x的倍数。可以求得最小的k=x-a%x。

并取(a+k)*(b+k)/gcd(a+k, b-a)为最小值时的k作为答案。

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

#include <bits/stdc++.h>
#define SINGLE_INPUT
#define ll long long
#define ull unsigned long long
#define N 500005
#define MOD 998244353
using namespace std;

void sol() {
ll a, b;
cin >> a >> b;
if (a > b)
swap(a, b);
ll x = b - a, mn = a * b / gcd(a, b), ans = 0;
auto upd = [&](ll f) {
ll k = f - a % f;
if ((a + k) * (b + k) / f < mn) {
mn = (a + k) * (b + k) / f;
ans = k;
}
};
for (int i = 1; i * i <= x; i++) {
if (x % i == 0) {
upd(i);
upd(x / i);
}
}
cout << ans << "\n";
}

int main() {
cout << setprecision(15) << fixed;
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifndef SINGLE_INPUT
int t;
cin >> t;
while (t--) {
sol();
}
#else
sol();
#endif
return 0;
}