UVA11388 GCD LCM
Description of the title
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)
暴力代码
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即可确定
证毕
又水了一篇题解鸭