P1029 最大公约数和最小公倍数问题
首先你要知道一点:
若A×B代表二者的乘积,也就是二者最大的乘积,
如果用A×B除以二者的最小公倍数,就能得到了二者的最大公约数
当然前提是这两个数要是非零的两个整数
最大公约数=A×B/最小公倍数
反过来,最小公倍数=A×B/最大公约数
那么这道题就很简单地做出来了:
方法一:枚举
①
#include<iostream> #include<cmath> using namespace std; int gcd(int a,int b)//求最大公约数 { while(b!=0)//辗转相除法求最大公约数 { int qwq=a%b; a=b; b=qwq; } return a; //return b == 0 ? a : gcd(b,a%b); } int main() { int x,y; cin>>x>>y;//输入最大公约数以及最小公倍数 int v=x*y;//最大值 int s=(int)sqrt(v);//不用重复进行寻找 int n=0; for(int i=x;i<=s;i++) if((v%i==0)//如果最大值能够整除当前的数,则说明找到了一组可能是真的的解 &&(gcd(v/i,i)==x))//如果另外一个数与当前的数的最大公约数等于输入的最大公约数 n++;//进行计数 cout<<n*2;// 不进行重复的筛之后要加上另一块的 return 0; }
②
#include <iostream> #include <cstdio> #define LL long long using namespace std; LL gcd(LL a,LL b) { return b ? gcd(b,a%b) : a; } int main() { LL Gcd,Lcm,ans=0; cin>>Gcd>>Lcm; LL Max=Gcd*Lcm; for(int i=Gcd; i<=Lcm; i++) for(int j=Gcd; j<=Lcm; j++) { if(i*j>Max) continue; if(gcd(i,j)!=Gcd) continue; if(i*j==Max) ans++; } cout<<ans; return 0; }
方法二:分解质因数(最优)
思路:
题目要求最大公约数(gcd)为3,最小公倍数(lcm)为60的两个数p、q的组数,两个数都去掉gcd后,即样例中的3、60变为1、20。
这样即可变为求gcd为1,lcm为20的两个数p、q的组数,即找两个互质的数,他们的乘积为20。
那么可以对20进行质因数分解,得:2、2、5。
盯住其中一个数,从质因数中选择。由于两个数要求互质,所以相同的质因数要合并,得到:4、5。
选法有2^2=4种:1,4,5,20。对应的四组答案即:1-20,4-5,5-4,20-1。
乘以gcd得到原来题目答案:3-60,12-15,15-12,60-3。
#include<iostream> #include<cstdio> #include<cmath> using namespace std; int main() { int x,y,z,k=0,i;//k为不同质因数的个数 scanf("%d%d",&x,&y); if(y%x!=0) printf("%d ",0); else { z=y/x;//除以最大公约数x for(i=2; i<=z; ++i) { //质因数分解 if(z%i==0) { ++k; while(z%i==0)z=z/i;//合并相同的质因数 } } printf("%d ",int(pow(2,k))); } return 0; }