一、题目
描述
输入两个正整数 x0,y0,求出满足下列条件的P,Q的个数:1.P,Q 是正整数。2.要求P,Q以 x0为最大公约数,以 y 0为最小公倍数。
试求:满足条件的所有可能的 P,Q 的个数。
输入描述
一行两个正整数x0,y0(2≤x0,y0≤105 ) 。
输出描述
一行一个数,表示求出满足条件的 P,Q 的个数。
用例输入 1
10 20
用例输出 1
2
用例输入 2
3 60
用例输出 2
4
二、思路
(1).首先要知道怎么求最大公约数和最小公倍数,最大公约数就递归或者辗转相除
(1)递归:
int gcd(int a,int b)
{
while(b>0)
{
if(a%b==0) return b;
else return gcd(b,a%b);//这样写的可以提高代码效率,而且比较方便
}
}
(2)辗转相除就不介绍了,可以去了解了解(这个属于迭代法)
要是想更简单,可以用c++的库函数__gcd(a,b),注意gcd前面是两个下划线,这个更快
(2).知道怎么求之后,就要想怎么去写才能实现。数学知识:最大公约数和最小公倍数的乘积等于两个数的乘积,即sum=ab=xy;(a<=b),所以两个数一定可以被sum整除 ;此时我们知道,两个数中最小数一定小于sqrt(a,b)或sqrt(xy);然后我们可以想想,假如ab(x*y)已知,我们就只需要找他们的因子(就是除自身外能被他整除的数(包括1)),即从1开始遍历,然后找因子,然后再有个判断最大公约数的公式即可判断
三、代码实现+注释
(1).第一种思想
#include <bits/stdc++.h>
#include<algorithm>
using namespace std;
int main()
{
long long n,m,cnt=0;
cin>>m>>n;
//当最大公约数=最小公倍数,那交换两个数答案是一样的,例如:10 10;
if(m==n) cnt--;
for(long long i=1;i<=sqrt(n*m);i++)
{
//如果i能被整除并且i带进去能够满足__gcd(),就说明找到了一对数
if(n*m%i==0&&__gcd(i,n*m/i)==m)
{
//因为最大公约数和最大公倍数交换位置的时候也成立;
cnt+=2;
}
}
cout<<cnt;
return 0;
}
(2)第二种思路:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll gcd(ll i,ll j)
{
if(i%j==0) return j;
else return gcd(j,i%j);
}
int main()
{
ll m,n,cnt=0;
cin>>m>>n;
//因为m为最大公约数,自然是最小的,而最大的就是最小公倍数n,直接遍历
for(ll i=m;i<=n;i++)
{
//i*j==m*n;
ll j=m*n/i;
if(gcd(i,j)==m&&i*j/gcd(i,j)==n)
{
//只要满足一次就加一次,注意不是加两次,因为这次是直接整体遍历,他会遍历到另一部分的
cnt+=1;
}
}
cout<<cnt;
return 0;
}
四、总结:
总的来说,这个题主要就是考最大公约数和最小公倍数的求法,以及相关函数的运算,建议大家先自己模拟函数,不要一上来就直接用c++的库函数,模拟算法可以训练自己的思维能力

828

被折叠的 条评论
为什么被折叠?



