C. Neko does Maths time limit per test:1 second memory limit per test:256 megabytes input:standard input output:standard output
Neko loves divisors. During the latest number theory lesson, he got an interesting exercise from his math teacher.
Neko has two integers a and b. His goal is to find a non-negative integer k such that the least common multiple of a+k and b+k is the smallest possible. If there are multiple optimal integers k, he needs to choose the smallest one.
Given his mathematical talent, Neko had no trouble getting Wrong Answer on this problem. Can you help him solve it?
InputThe only line contains two integers a and b (1≤a,b≤10^9).
OutputPrint the smallest non-negative integer k (k≥0) such that the lowest common multiple of a+k and b+k is the smallest possible.
If there are many possible integers k giving the same value of the least common multiple, print the smallest one.
Examples| input |
| 6 10 |
| output |
| 2 |
| input |
| 21 31 |
| output |
| 9 |
| input |
| 5 10 |
| output |
| 0 |
In the first test, one should choose k=2, as the least common multiple of 6+2 and 10+2 is 24, which is the smallest least common multiple possible.
題解
假設a <= b,根據LCM和GCD的關系知:LCM(a,b) = a*b/GCD(a,b),要求最小的k滿足最小的LCM(a+k,b+k) = (a+k)*(b+k)/GCD(a+k,b+k),由更相減損法知,GCD(a+k,b+k) = GCD(a+k,b-a),這樣就使得GCD中有一項(即b-a)是固定的,這樣有什么好處呢?沒錯,就是GCD(a+k,b-a)的結果一定是b-a的某個因子,而b-a的所有因子是有限個,且可以在sqrt(b-a)的時間內求出,故列舉b-a所有的因子即可,對于b-a的每一個因子di,都可以求出最小的ki = di - a%di (a%di != 0) 或者ki = 0 (a%di == 0),再代回公式計算,保留使得LCM(a+k,b+k)最小的k即可,
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #define re register 8 #define il inline 9 #define ll long long 10 #define ld long double 11 const ll MAXN = 1e6+5; 12 const ll INF = 1e8; 13 14 ll f[MAXN]; 15 16 //快讀 17 il ll read() 18 { 19 char ch = getchar(); 20 ll res = 0, f = 1; 21 while(ch < '0' || ch > '9') 22 { 23 if(ch == '-') f = -1; 24 ch = getchar(); 25 } 26 while(ch >= '0' && ch <= '9') 27 { 28 res = (res<<1) + (res<<3) + (ch-'0'); 29 ch = getchar(); 30 } 31 return res*f; 32 } 33 34 //輾轉相除法 35 ll gcd(ll a, ll b) 36 { 37 ll mx = std::max(a,b); 38 ll mi = std::min(a,b); 39 return mi == 0 ? mx : gcd(mi,mx%mi); 40 } 41 42 int main() 43 { 44 ll a = read(); 45 ll b = read(); 46 ll mx = std::max(a,b); 47 ll mi = std::min(a,b); 48 ll tot = 0; 49 ll c = mx-mi; 50 ll n = sqrt(c); 51 //列舉c的所有因子 52 for(re ll i = 1; i <= n; ++i) 53 { 54 if(!(c%i)) 55 { 56 f[++tot] = i; 57 f[++tot] = c/i; 58 } 59 } 60 //依次代回c的因子計算 61 ll k = 0; 62 ll d = a*b/gcd(a,b); 63 for(re ll i = 1; i <= tot; ++i) 64 { 65 ll tk = !(mi%f[i]) ? 0 : f[i]-mi%f[i]; 66 ll td = (a+tk)*(b+tk)/f[i]; 67 if(td <= d) 68 { 69 if(td == d) k = std::min(k,tk); //二者相同取最小的k 70 else k = tk; 71 d = td; 72 } 73 } 74 printf("%lld\n", k); 75 return 0; 76 }View Code
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/105922.html
標籤:C++
上一篇:重寫二路歸并排序
