NO.5 题析 0327周训练 P1029最大公约数和最小公倍数问题

题目描述

输入两个正整数 x_0, y_0x0​,y0​,求出满足下列条件的 P, QP,Q 的个数:

  1. P,QP,Q 是正整数。

  2. 要求 P, QP,Q 以 x_0x0​ 为最大公约数,以 y_0y0​ 为最小公倍数。

试求:满足条件的所有可能的 P, QP,Q 的个数。

输入格式

一行两个正整数 x_0, y_0x0​,y0​。

输出格式

一行一个数,表示求出满足条件的 P, QP,Q 的个数。

说明/提示

P,QP,Q 有 44 种:

  1. 3, 603,60。
  2. 15, 1215,12。
  3. 12, 1512,15。
  4. 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;
}
  1. 辗转相除,递归,求最大公约数
  2. 如果gcd与lcm相等,则需要减去一次(因为不存在相反),如不减,90分
  3. 求出gcd与lcm积
  4. 遍历sqrt(ans),因为后面的会重复
  5. 满足两个条件,则P,Q成立
  6. 因为前面没有全部遍历,所以回出现相反结果,n+=2;
  7. 在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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值