题解 P1029 【最大公约数和最小公倍数问题】
本文符号简述(大佬自行跳过):
可得
证明如下:
可设
得证。
那么怎样求
又有定理:
证明如下:
若想证明上式,则需证明:
①.
a 和b 的任一约数都是b 和a \% b 的约数
②.
b 和a \% b 的任一约数都是a 和b 的约数
设
则
设
则
①.得证
同理可证②.
则定理得证。
那么,求
实现:
inline int gcd(int x,int y)
{
if(y==0) return x;
return gcd(y,x%y);
}
那么问题来了,这只是最大公约数,那最小公倍数呢?
又有定理:
两个数最大公约数与最小公倍数的乘积即为这两个数的乘积
证明:
设两个数为
设
假设
则分两种情况讨论:
-
若有更大的
p_1p_2 满足条件 ,则此时a 不取最大值 ,矛盾 -
若有更大的
a 满足条件 ,矛盾
综上:
定理得证
那么此题算法也就清楚了。
枚举xy的所有因数
#include <bits/stdc++.h>
using namespace std;
int x,y;
inline int gcd(int x,int y)
{
if(y==0) return x;
return gcd(y,x%y);
}
int main()
{
cin>>x>>y;
int ans=0;
for(int i=1;i<=sqrt(x*y);i++)
{
if(x*y%i==0&&gcd(i,x*y/i)==x) ans++;
}
cout<<ans*2;
return 0;
}
然后你发现错了一个点。
其实如果
此时,
#include <bits/stdc++.h>
using namespace std;
int x,y;
inline int gcd(int x,int y)
{
if(y==0) return x;
return gcd(y,x%y);
}
int main()
{
cin>>x>>y;
int ans=0;
for(int i=1;i<=sqrt(x*y);i++)
{
if(x*y%i==0&&gcd(i,x*y/i)==x) ans++;
}
ans*=2;
if(x==y) ans--;
cout<<ans;
return 0;
}
其实还有一点不完美,就是
#include <bits/stdc++.h>
using namespace std;
long long x,y;
inline long long gcd(long long x,long long y)
{
if(y==0) return x;
return gcd(y,x%y);
}
int main()
{
cin>>x>>y;
long long ans=0;
for(long long i=1;i<=sqrt(x*y);i++)
{
if(x*y%i==0&&gcd(i,x*y/i)==x) ans++;
}
ans*=2;
if(x==y) ans--;
cout<<ans;
return 0;
}