题目传送门:CodeForces-1152C Neko does Maths
题目大意:
给你两个值a,b,让你求出使lcm(a+k,b+k),最小的k值
gcd性质:
gcd性质:gcd(a,a) = gcd(a,a)
gcd(a,b) = gcd(a,a-b)(a>b)
gcd(a,b) = gcd(b,a-b)(a>b)
证明:设gcd(a,b)=z; a=zx ,b=zy ,a-b=z(x-y)
要证明a-b和b的gcd等于a和b的gcd
b=zy a-b=z(x-y) 则需要证明y和x-y互质即可,这样他们gcd同为z
x和y显然为质数,存在两种情况
x和y其中不存在2:设x=2m-1 y=2n-1,则x-y=2(m-n)为一个偶数,显然x-y和质数y互质
x和y其中存在2:设x=2m+1 y=2 ,则x-y=2m-1 显然x-y和2互质。
成立。
分析:
lcm(a+k,b+k) = (a+k)*(b+k) / gcd(a+k,b+k). 要使得lcm(a+k,b+k)最小,则需要gcd(a+k,b+k)最大
设gcd(a+k,b+k) = z. 则存在 (a+k)%z = (b+k)%z = 0; a%z = b%z (a - b) % z = 0
所以 a+k 和 b+k 的最大公约数z,是(a-b)的约数。
因为gcd(a+k,b+k)=gcd(a+k,a-b)
因此可以枚举(a-b)的因子,将a+k凑至存在该因子,则k =(x-a%x)(x为因子),进行判断lcm即可。
代码:
#include<iostream> using namespace std; typedef long long ll; ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b); } ll lcm(ll a,ll b){ return a*b/gcd(a,b); } ll a,b,mmax,ans=0; void solve(int x) { int temp=x-a%x; //将a凑至存在因子x if(lcm(a+temp,b+temp)<mmax){ ans=temp; mmax=lcm(temp+a,b+temp); } } int main(){ cin>>a>>b; if(a<b)swap(a,b); int c=a-b; mmax=lcm(a,b); for(int i=1;i*i<=c;i++){ //枚举a-b的因子 if(c%i==0){ solve(i); solve(c/i); } } cout<<ans<<endl; return 0; }
参考:https://www.cnblogs.com/dancewithautomation/archive/2012/06/23/2559451.html