Codeforces Round #554 (Div. 2) C. Neko does Maths 数论

题目链接
题意:输入两个数 a, b,让你求可以使得(a+k)与 (b+k)的最小公倍数最小的情况下的最小的k.
思路: lcm(a+k, b+k) = (a+k)*(b+k)/gcd(a+k, b+k),又gcd(a+k, b+k) = gcd(a-b, a+k),令d = gcd(a+k, b+k),则 d 一定为a-b的因子,若知道d则可以求出k = d - a%d,也就可以求出lcm(a+k, b+k),所以我们选择暴力的方式去遍历a-b的因子,再取这个最小lcm对应的k就是答案。

d = gcd(a-b, a+k),求出k的过程 => (a+k)%d = 0; 即((a % d + k % d) % d = 0),所以 a%d + k%d = d 或者 a%d + k%d = 0,令 a = x*d + r, k = y*d + s,则(x*d + r) % d + (y*d + s) % d = d 或者(x*d + r) % d + (y*d + s) % d = 0;即 r + s = d 或者 r + s = 0。由于 k = y*d + s 要最小值,所以 k = s,所以 r + k = d 或者 r + k = 0; 而 r = a%d,所以 k = d - a%d

AC代码:

#include
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define show(x) cout< iip;
typedef pair llp;
const int MAXN = 1000005;
const int INF = 0x3f3f3f3f;
const int MOD = 998244353;

int i, j, a, b, ans;
vector v;

struct node {
    ll lcm;
    int k;
    bool operator < (const node &y) const {
        if(lcm == y.lcm) return k < y.k;
        return lcm < y.lcm;
    }
}x[MAXN];

ll gcd(ll x, ll y) {
    return y == 0 ? x : gcd(y, x % y);
}

ll LCM(ll x, ll y) {
    return x * y / gcd(x, y);
}

int main()
{
    IO
    cin>>a>>b;
    if(a < b)   swap(a, b);
    int tmp = a - b;
    for(i = 1; i * i <= tmp; i++) {
        if(tmp % i == 0) {
            v.push_back(i);
            if(i != tmp/i)  v.push_back(tmp / i);
        }
    }
    i = 0;
    for(int d : v) {
        x[i].k = d - a % d;
        x[i++].lcm = LCM((a + x[i].k) , (b + x[i].k));
    }
    x[i].k = 0;
    x[i++].lcm = LCM(a, b);
    sort(x, x+i);
    cout<

你可能感兴趣的:(Codeforces Round #554 (Div. 2) C. Neko does Maths 数论)