洛谷 UVA11388 GCD LCM

UVA11388 GCD LCM

Description of the title

PDF

The GCD of two positive integers is the largest integer that divides both the integers without any remainder.

The LCM of two positive integers is the smallest positive integer that is divisible by both the integers.

A positive integer can be the GCD of many pairs of numbers.

Similarly, it can be the LCM of many pairs of numbers.

In this problem, you will be given two positive integers.

You have to output a pair of numbers whose GCD is the first number and LCM is the second number.

Input

The first line of input will consist of a positive integer T.

T denotes the number of cases.

Each of the next T lines will contain two positive integer, G and L.

Output

For each case of input, there will be one line of output.

It will contain two positive integers a and b, a ≤ b, which has a GCD of G and LCM of L.

In case there is more than one pair satisfying the condition, output the pair for which a is minimized.

In case there is no such pair, output ‘-1’.

Constraints

• T ≤ 100

• Both G and L will be less than 231 .

Sample Input

2 1 2 3 4

Sample Output

1 2 -1

Solution

This is a Chinese puzzle!

请记住,看到gcd/lcm,先想数论,而不是暴力!

想不出来再打表找规律!

普及- 的题,不是模拟就是数论。       ——佚名(我)

Algorithm(Naive)

暴力代码

洛谷 UVA11388 GCD LCM
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 inline unsigned long long gcd(unsigned long long a,unsigned long long b)
 4 {
 5     if(b==0) return a;
 6     if(b==1) return 1;
 7     if(a%2==0&&b%2==0) return 2*gcd(a/2,b/2);
 8     if(a%2==1&&b%2==0) return gcd(a,b/2);
 9     if(a%2==0&&b%2==1) return gcd(a/2,b);
10     if(a%2==1&&b%2==1) return gcd(b,a%b);
11 //    return (b==0)?a:gcd(b,a%b);
12 }
13 unsigned long long t,a,b,j,g,l,flag;
14 int main()
15 {
16     cin>>t;
17     while(t--)
18     {
19         cin>>g>>l;
20         j=g*l;
21         flag=1;
22         for(int a=1;a*a<=j;a++)
23         {
24             if(j%a==0)
25             if(gcd(a,j/a)==g){
26                 cout<<a<<" "<<j/a<<endl;
27                 flag=0;
28                 break;
29             }
30         }
31         if(flag) cout<<"-1\n";
32     }
33 
34     return 0;
35 }
朴素算法Code

时间复杂度

O(t sigma log(sqrt(1 to g*j)))

understand

没脑子的我都懂怎么暴力了……

i*j==g*l

Algorithm(Arithmetical)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 unsigned long long t,g,l;
 4 int main()
 5 {
 6     cin>>t;
 7     while(t--)
 8     {
 9         cin>>g>>l;
10         if(l%g==0)
11             cout<<g<<" "<<l<<endl;
12         else
13             cout<<"-1\n";
14     }
15     return 0;
16 }

时间复杂度

O(t)

Understand

这个要一点脑子哈

首先,若有两个数i,j

且g=gcd(i,j),l=lcm(i,j);

那么,

l | g

即g整除l

证明:

从文字的角度理解

lcm,两数最小的公倍数,那么l一定是i,j的倍数

gcd,两数最大的公因数,那么g一定是i,j的因数

那么l有因数i,j

当然也有因数g!

证毕

所以l%g==0

否则,直接输出-1

 

但是如何确定:(g,l)就是i最小,j最大的一组解呢?

设n=i/g

由g是i,j的gcd

所以g是i的因子

即i是g的倍数

那么定有n为正整数

那么n的最小值为1

此时i==gcd(i,j)

又因为i不能比g小

故i的最小值即为g

此时的g,imin,j已确定

根据公式i*j=gcd(i,j)*lcm(i,j)

jmax即可确定

证毕

又水了一篇题解鸭

上一篇:2019年东北四省赛感想


下一篇:关于一些数论问题例题的讨论