P1029 [NOIP2001 普及组] 最大公约数和最小公倍数问题
最大公约数和最小公倍数的关系
两个数的乘积等于这两个数的最大公约数和最小公倍数的乘积
最小公倍数
最小公倍数等于这两个数所有公有质因数和各自独有的质因数相乘的积。所以这两个数的最小公倍数一定是这两个数所有公有质因数的乘积的倍数,即这两个数的最小公倍数一定是这两个数最大公因数的倍数。
最大共因数
两个数的最大公因数等于这两个数所有公有质因数的乘积,所以两个数的最大公因数等于这两个数的最大公约数和最小公倍数的乘积,就相当于把两个数都分解成若干个质因数的乘积,挑出公共的部分只选一次,归为最大公因数,公共的部分只选一次,再加上不同的部分,归为最小公倍数。
根据上面的两个数的乘积等于这两个数的最大公约数和最小公倍数的乘积,这道题的思路就是遍历sqrt(xy)所有的数,不用遍历所有的,找出它的能跟它相乘等于xy的数,然后还要再判断一下,(找的时候可能会有最大公约数变化,最小公倍数变化的),只需要再判断这两个数的最大公倍数是不是x,因为已经确保了它们的乘积等于x*y,只要一个没变另一个也不会变。
#include<iostream>
#include<cmath>
using namespace std;
long long gcd(long long a,long long b)
{
if(b==0) return a;
return gcd(b,a%b);
}
int main()
{
long long x,y;
long long ans = 0;
cin>>x>>y;
if(x==y) ans --; //当x=y时会有重复减去一个
for(int i=x;i<=sqrt(x*y);i++) //遍历到sqrt(x*y) 这样得到的就是前面的小于后面的 只用遍历一半
{
if(x*y%i==0&&x==gcd(i,x*y/i)) //还要再判断一下最小公倍数是不是题中要求的(检查最小公倍数和最大)
ans += 2; //这里+=2 前大后小 和 前小后大是一样的
}
cout<<ans<<endl;
return 0;
}
哭了,看题解写的,这个数学知识我怎么不知道啊,啊啊啊,菜菜,记住记住,加油加油