link:http://codeforces.com/problemset/problem/1152/C
题目大意:题目要求是求一个k使得(a+k)*(b+k)/ __gcd(a+k,b+k)最小,且在最小的公倍数中找到最小的k.
方法:重点在于:__gcd(a+k,b+k),而__gcd(a+k,b+k)=__gcd(abs(a-b),a+k) (这也可以是__gcd( abs(a-b) ,b+k) ),而gcd( abs(a-b) ,a+k) 一定是abs(a-b) 的因子,找出因子后通过倒推求出k,具体如下:
当(a+k)%因子 != (b+k)%因子 时,即a%因子 != b%因子,表示这个因子不是gcd(a+k,b+k),排除。
当....................==.....................时,表示这个因子就是gcd(a+k,b+k),判断一下题目要求,再求出k(=因子-a%因子)。
红字来由:
//http://codeforces.com/problemset/problem/1152/C
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
ll a,b;
void solve(){
ll i,j;
ll d=abs(a-b);
vector<ll> v;
for(i=1;i*i<=d;++i){
if(d%i==0){
v.push_back(i);
if(i*i!=d){
v.push_back(d/i);
}
}
}
ll ansg=(1ll<<62),ans=0;
sort(v.begin(),v.end());
for(i=0;i<v.size();++i){
int t=v[i];
if(a%t!=b%t) continue;
else if(a%t==0){
ll g=a*b/__gcd(a,b);
if(ansg>g){
ansg=g;
ans=0;
}
}
else{
ll g=(a+t-a%t)*(b+t-b%t)/__gcd((a+t-a%t),(b+t-b%t));
if(g<ansg){
ansg=g;
ans=t-a%t;
}
}
}
cout<<ans<<endl;
}
int main(){
cin>>a>>b;
solve();
return 0;
}

博客围绕一道题目展开,题目要求找到一个k,使(a+k)*(b+k)/ __gcd(a+k,b+k)最小,并在最小公倍数中找出最小的k。重点在于__gcd(a+k,b+k),它等于__gcd(abs(a - b),a + k),通过找出abs(a - b)的因子,倒推求出符合条件的k。
453

被折叠的 条评论
为什么被折叠?



