Codeforces Round #554 (Div. 2) C. Neko does Maths (数论 GCD(a,b) = GCD(a,b-a))

传送门

题意

  给出两个正整数 a,b;

  求解 k ,使得 LCM(a+k,b+k) 最小,如果有多个 k 使得 LCM() 最小,输出最小的k;

•思路

时隔很久,又重新做这个题

温故果然可以知新❤

重要知识点

GCD(a,b)=GCD(a,b-a)=GCD(b,b-a) (b>a)

证明:

设GCD(a,b)=c

则a%c=0,b%c=0,(b-a)%c=0

所以GCD(a,b-a)=c

得GCD(a,b)=GCD(a,b-a)

思路一:

gcd(a+k,b-a)肯定是(b-a)的因子

所以gcd(a+k,b+k)是(b-a)的因子,所以我们就枚举(b-a)的因子(把因子称为i)

使得 (a+k)为i的倍数

解出k,再判断lcm是否符合最小

注意这里枚举的i只是(a+k)和(b+k)的公约数,不一定是最大公约数gcd

两者的公约数得到的是公倍数  公倍数=a*b/公约数

如果是最大公约数的话两者的公倍数一定是最小,

这里是没有甄别是否是最大公约数而是简单的得到公约数,然后得到的是公倍数

在所有的公倍数中,最小公倍数是最小的

所以并不影响解最小公倍数的答案

例如:

12 30

12 30
a+k=13 b+k=31 公约数i=1   公倍数=403   k=1
a+k=18 b+k=36 公约数i=18 公倍数=36     k=6
a+k=14 b+k=32 公约数i=2   公倍数=224   k=2
a+k=18 b+k=36 公约数i=9   公倍数=72     k=6
a+k=15 b+k=33 公约数i=3   公倍数=165   k=3
a+k=18 b+k=36 公约数i=6   公倍数=108   k=6

最小公约数36,此时k=6

•代码

 1 //#include<bits/stdc++.h>
 2 //using namespace std;
 3 //#define ll long long
 4 //#define inf 0x3f3f3f3f
 5 //ll ans=inf;
 6 //ll a,b;
 7 //ll lcm;
 8 //
 9 //ll __lcm(ll x,ll y)
10 //{
11 //    return x*y/__gcd(x,y);
12 //}
13 //
14 //
15 //void Slove(int f)
16 //{
17 //    int x=a/f+(a%f!=0);
18 //    int y=(b-a)/f;
19 //    if(__gcd(x,y)==1)
20 //    {
21 //        if(__lcm(x*f,y*f)<lcm)
22 //        {
23 //            lcm=__lcm(x*f,y*f);
24 //            ans=x*f-a;
25 //        }
26 //        if(__lcm(x*f,y*f)==lcm)
27 //            ans=min(ans,x*f-a);
28 //    }
29 //    else
30 //    {
31 //        if(__lcm((x+1)*f,y*f)<lcm)
32 //        {
33 //            lcm=__lcm((x+1)*f,y*f);
34 //            ans=(x+1)*f-a;
35 //        }
36 //        if(__lcm((x+1)*f,y*f)==lcm)
37 //            ans=min(ans,(x+1)*f-a);
38 //    }
39 //}
40 //
41 //int main()
42 //{
43 //    cin>>a>>b;
44 //    if(b<a)
45 //        swap(a,b);
46 //    lcm=a*b/__gcd(a,b);
47 //
48 //    if(a==b)
49 //        ans=0;
50 //    else
51 //    {
52 //        for(ll i=1;i*i<=b-a;i++)
53 //        {
54 //            if((b-a)%i==0)
55 //            {
56 //                Slove(i);
57 //                Slove((b-a)/i);
58 //            }
59 //        }
60 //    }
61 //    cout<<ans<<endl;
62 //}
63 
64 
65 #include<bits/stdc++.h>
66 using namespace std;
67 #define ll long long
68 ll a,b;
69 ll ans,lcm=0x3f3f3f3f3f3f3f3f;
70 int main()
71 {
72     cin>>a>>b;
73     ll d=abs(a-b);
74     for(ll i=1;i*i<=d;i++)
75     {
76         if(d%i==0)//枚举b-a的因数i
77         {
78             ll k=i-a%i;//把a凑成i的倍数需要+k
79             ll t=(a+k)*(b+k)/i;// a*b/i得公倍数
80             if(t<lcm)
81             {
82                 lcm=t;
83                 ans=k;
84             }
85 
86             ll ii=d/i;
87             k=ii-a%ii;
88             t=(a+k)*(b+k)/ii;
89             if(t<lcm)
90             {
91                 lcm=t;
92                 ans=k;
93             }
94         }
95     }
96     cout<<ans<<endl;
97 }
View Code

猜你喜欢

转载自www.cnblogs.com/MMMinoz/p/11240607.html