Codeforces Round #554 (Div. 2) C.Neko does Maths (gcd的运用)
题目链接:https://codeforces.com/contest/1152/problem/C
题目大意:给定两个正整数a,b,其中(1<=a,b<=1e9),求一个正整数k(0<=k),使得a+k与b+k的最小公倍数最小。
解题思路:首先我们需要知道gcd(a,b)=gcd(a,b-a)=gcd(b,b-a)(b>a)的
我们要求的是lcm(a+k,b+k)=(a+k)(b+k)/gcd(a+k,b+k)=(a+k)(b+k)/gcd(a+k,b-a)
因为b-a是定值,所以我们可以枚举每个b-a的约数设为x,然后我们计算出最小的k使得(a+k)%x==0,然后计算他们的最小公倍数,如果大于我们的当前最小公倍数就更新。
代码:
#include<iostream> #include<cstdio> #include<vector> #include<cstring> using namespace std; typedef long long ll; const int mod=1e9+7; ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} ll lcm(ll a,ll b){return a/gcd(a,b)*b;} const int maxn=2e5+7; vector<ll> yinzi; int main(){ ll a,b; cin>>a>>b; if(a>b)swap(a,b); if(a==b||b%a==0||b-a==1){ cout<<0<<endl; return 0; } int cha=b-a; for(int i=1;i*i<=cha;i++){ //计算b-a的所有因子 if(cha%i==0){ yinzi.push_back(i); if(i*i!=cha) yinzi.push_back(cha/i); } } ll ans=lcm(a,b),x=0; for(int i=0;i<yinzi.size();i++){ int k=0; if(a%yinzi[i]) k=yinzi[i]-a%yinzi[i]; if(k>=0){ ll tmp=(a+k)/yinzi[i]*(b+k); if(tmp==ans&&k<x) x=k; if(tmp<ans){ ans=tmp; x=k; } } } cout<<x<<endl; return 0; }