CF1152C Neko does Maths

mac2024-03-09  27

题目描述

(描述为翻译,翻译来自洛谷) 给定两个正整数a,b,找到非负整数k使a+k与b+k的最小公倍数最小,如有多解输出最小的k

a , b ≤ 1 0 6 a ,b ≤ 10^6 a,b106 对于这种题我们显然需要一些数论知识来帮助我们找到思路 那么我们首先想到的是lcm和gcd是有关系的 即 l c m ( a , b ) = a ∗ b g c d ( a , b ) lcm(a,b) = \frac{a*b}{gcd(a,b)} lcm(a,b)=gcd(a,b)ab 那么在这道题中就是 l c m ( a + k , b + k ) = ( a + k ) ∗ ( b + k ) g c d ( ( a + k ) , ( b + k ) ) lcm(a+k, b+k) = \frac{(a+k) * (b+k)}{gcd((a+k), (b+k))} lcm(a+k,b+k)=gcd((a+k),(b+k))(a+k)(b+k) 然后我们可以想到gcd的一些性质 那么由更相减损术我们可以知道 g c d ( a , b ) = g c d ( b , a − b ) gcd(a,b) = gcd(b,a-b) gcd(a,b)=gcd(b,ab)其中,a >b; 那么我们就可以把原式子中的 g c d ( a + k , b + k ) gcd(a+k,b+k) gcd(a+k,b+k)写成 g c d ( b + k , a − b ) gcd(b+k, a-b) gcd(b+k,ab) 那么我们考虑,设 x = g c d ( b + k , a − b ) x = gcd(b+k, a-b) x=gcd(b+k,ab)那么x一定是a-b的因子的其中一个,这时候我们只需要算出一个k使x是b+k和a-b的gcd我们就可以求出一个lcm, 这里当 b m o d    x = = 0 b\mod x == 0 bmodx==0时k = 0; !=时 k = b/x * x + x; 这里的除是向下取整,这样就保证了x是b+k的最大因子。 因此我们可以枚举a-b的所有因子,求出对应的k和lcm,对于每个结果进行比较求min即可。

没想到的是,k是会爆ll的 所以记得开ll写

C o d e Code Code

#include<bits/stdc++.h> #define INF 0x3f3f3f3f #define ll long long using namespace std; inline ll gcd(ll a, ll b){//没用 return a % b == 0 ? b : gcd(b, a % b); } ll a, b, k, t; ll ans = 1e18; int main() { cin >> a >> b; if(a < b){ a ^= b, b ^= a, a ^= b; } ll num = 1e18; for(ll i = 1; i * i <= a-b; ++i){//i,j都为枚举的因子 ll tk; if((a-b) % i == 0){ ll j = (a-b) / i; if(b % i == 0) tk = 0; else tk = (b / i + 1) * i - b; ll num = (a + tk) * (b + tk) / i; if(num < ans) ans = num, k = tk; if(num == ans) k = min(k, tk); if(b % j == 0) tk = 0; else tk = (b/j + 1) * j - b; num = (a + tk) * (b + tk) / j; if(num < ans) ans = num, k = tk; else if(num == ans) k = min(k, tk); } } cout << k << endl; }
最新回复(0)