CF 552 Neko does Maths

给出两个数a,b  

求k     使得 a+k b+k有最小公倍数

a,b同时加上一个非负整数k,使得,a+k,b+k的最小公倍数最小

因为最小公公倍数=x*y / gcd(x,y),所以肯定离不开最大公约数了;

首先有个结论 gcd(x,y)=gcd(x,y-x) (y>x)

令c=gcd(x,y),那么x%c=0,y%c=0,(y-x)%c=0,所以gcd(x,y)=gcd(x,y-x)

因为题目中d=x-y的值不会变,所以我们就可以通过枚举d的因子,来凑a+k (d的因子也是(a+k)的因子)

拓展欧几里德 算法 待学。。。

#include<bits/stdc++.h>
using namespace std;
using LL = long long;
LL gcd(LL a, LL b){
    return b ? gcd(b, a % b) : a;
}
LL lcm(LL a, LL b){
    return a * b / gcd(a, b);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    //gcd(a + k, b + k) == gcd(a - b, a + k);
    LL a, b;
    cin >> a >> b;
    if(a < b) swap(a, b);
    LL x = abs(a - b), ans = lcm(a, b), ansk = 0;
    for(LL i = 1, k; i * i <= x; i += 1) if(x % i == 0){
        k = i - a % i;
        if(lcm(a + k, b + k) < ans){
            ans = lcm(a + k, b + k);
            ansk = k;
        }
        k = x / i - a % (x / i);
        if(lcm(a + k, b + k) < ans){
            ans = lcm(a + k, b + k);
            ansk = k;
        }
    }
    if(a > b){
        
    } 
    cout << ansk;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/bxd123/p/10770646.html