题目描述
输入二个正整数x0,y0(2<=x0<100000,2<=y0<=100000),求出满足下列条件的P,Q的个数
条件: 1.P,Q是正整数
2.要求P,Q以x0为最大公约数,以y0为最小公倍数.
试求:满足条件的所有可能的两个正整数的个数.
输入
一行两个正整数 x0, y0
输出
一行一个数,表示求出满足条件的 P, Q的个数。
样例输入
3 60
样例输出
4
提示/说明
P,Q 有4种:
1.3,60
2.15,12
3.12.15
4.60,3
对于 100% 的数据,2≤x0,y0≤10^5。
思路:
一道经典的gcd以及lcm的题(不装了其实就是最大公约数和最小公倍数)
gcd一个很重要的定理:gcd(x,y)*lcm(x,y)=x*y
依靠这个定理,只需要进行枚举,便可AC
一层for循环,i初始值为1,终止值为x*y
如果x*y%i==0(意思看上方定理理解)以及gcd(i,x*y/i)==x(检测两数gcd是否为x)
上AC代码(1):
# include <iostream>
# include <cstdio>
using namespace std;
# define int long long//有些题卡longlong,所以一行这个代码便可解决。要注意scanf和printf是要写成%lld,int main要写成signed main
int x,y,cnt=0;
int gcd(int a, int b){
if (b==0){
return a;
}
return gcd(b,a%b);
}
signed main(){
scanf("%lld%lld",&x,&y);
for (int i=1;i<=x*y;i++){
if (x*y%i==0&&gcd(i,x*y/i)==x){
cnt++;
}
}
printf("%lld",cnt);
return 0;
}
有的大神就要说了:你这时间复杂度不行啊,才O(xy),实在太低了
那就优化一下
首先,O(xy)最多降到O(sqrt(xy))
sqrt:开平方
画个图便可清晰的理解:
假设我们求x的因数个数 (因为也用到sqrt)
所以说,如果我们的代码要用到sqrt,最后的cnt就需要*2
上代码(2):
# include <iostream>
# include <cstdio>
# include <cmath>
using namespace std;
# define int long long
int x,y,cnt=0;
int gcd(int a, int b){
if (b==0){
return a;
}
return gcd(b,a%b);
}
signed main(){
scanf("%lld%lld",&x,&y);
for (int i=1;i<=sqrt(x*y);i++){
if (x*y%i==0&&gcd(i,x*y/i)==x){
cnt++;
}
}
cnt*=2;
printf("%lld",cnt);
return 0;
}
有些人就直接抄走了
还有问题吗?
当x==y时,不用sqrt结果为1,
用上sqrt结果成2了
所以说,还需要个特判
# include <iostream>
# include <cstdio>
# include <cmath>
using namespace std;
# define int long long
int x,y,cnt=0;
int gcd(int a, int b){
if (b==0){
return a;
}
return gcd(b,a%b);
}
signed main(){
scanf("%lld%lld",&x,&y);
if (x==y){
printf("1");
return 0;
}
for (int i=1;i<=sqrt(x*y);i++){
if (x*y%i==0&&gcd(i,x*y/i)==x){
cnt++;
}
}
cnt*=2;
printf("%lld",cnt);
return 0;
}
这会就能AC了
所以说,严禁抄代码
制作不易,点个赞再走吧