题目描述
输入两个正整数 x_0, y_0x0,y0,求出满足下列条件的 P, QP,Q 的个数:
-
P,QP,Q 是正整数。
-
要求 P, QP,Q 以 x_0x0 为最大公约数,以 y_0y0 为最小公倍数。
试求:满足条件的所有可能的 P, QP,Q 的个数。
输入格式
一行两个正整数 x_0, y_0x0,y0。
输出格式
一行一个数,表示求出满足条件的 P, QP,Q 的个数。
说明/提示
P,QP,Q 有 44 种:
- 3, 603,60。
- 15, 1215,12。
- 12, 1512,15。
- 60, 360,3。
对于 100\%100% 的数据,2 ≤x0,y0≤105。
题析
首先感谢@qinxiang123321大佬提供的题析
以下为秦想的题析
———————————————————————————————————————————
本题如果使用暴力枚举,套双重for循环,肯定是会超时的(0分),因此需要另寻他法:
本题的两个技巧
一.gcd*lcm=P*Q(gcd最大公约数,lcm最小公倍数)
二.使用辗转相除,求最大公约数
AC代码:
#include <iostream>
#include <cmath>
using namespace std;
int gcd(int a,int b)
{
if(a%b==0)
{
return b;
}
else
{
return gcd(b,a%b);
}
}
int main()
{
int x,y,n=0,ans=0;
cin>>x>>y;
if(x==y)
{
ans--;
}
n=x*y;
for(int i=1;i<=sqrt(n);i++)
{
if(n%i==0 && gcd(i,n/i)==x)
{
ans+=2;
}
}
cout<<ans<<endl;
return 0;
}
- 辗转相除,递归,求最大公约数
- 如果gcd与lcm相等,则需要减去一次(因为不存在相反),如不减,90分
- 求出gcd与lcm积
- 遍历sqrt(ans),因为后面的会重复
- 满足两个条件,则P,Q成立
- 因为前面没有全部遍历,所以回出现相反结果,n+=2;
- 在c++中存在gcd函数,但CSDN上解释不允许noip不让用
———————————————————————————————————————————
这里给出一个更加简洁的方法(但是还是谢谢秦想大佬)
一开始写ac实在太复杂了的就不加赘述了,直接讲与老师讨论后的精简代码罢
一个小学学过的知识,最大公约数和最小公倍数的乘积就是原两个数的积(什么你没学过?)
又一个小知识,__gcd是直接求最大公约数,这样两个数的积、最大公约数就都有了,我们只用枚举一个x再根据条件检索y就可以了!
这里还涉及到了一个优化的小点
因为假设枚举可以相乘等于10的数,那么是不是1*10和10*1都要枚举一遍?
所以直接开根就可以啦,这样枚举不会重复
每次检索到+2
两个数相等就+1
#include<bits/stdc++.h>
using namespace std;
int m,n,ans;
int main(){
cin>>m>>n;
if(m==n) ans--;//判断是否相等,相等则-1
n*=m;
for(int if(n%i==0&&__gcd(i,n/i)==m) ans+=2;//每次检索+2
}
cout<<ans;
return 0;
}
完awa