題目描述
(描述爲翻譯,翻譯來自洛谷)
給定兩個正整數a,b,找到非負整數k使a+k與b+k的最小公倍數最小,如有多解輸出最小的k
對於這種題我們顯然需要一些數論知識來幫助我們找到思路
那麼我們首先想到的是lcm和gcd是有關係的
即
那麼在這道題中就是
然後我們可以想到gcd的一些性質
那麼由更相減損術我們可以知道其中,a >b;
那麼我們就可以把原式子中的寫成
那麼我們考慮,設 那麼x一定是a-b的因子的其中一個,這時候我們只需要算出一個k使x是b+k和a-b的gcd我們就可以求出一個lcm,
這裏當時k = 0;
!=時 k = b/x * x + x; 這裏的除是向下取整,這樣就保證了x是b+k的最大因子。
因此我們可以枚舉a-b的所有因子,求出對應的k和lcm,對於每個結果進行比較求min即可。
沒想到的是,k是會爆ll的 所以記得開ll寫
#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;
}