【C++题解】两数问题

P a r t Part Part 1 1 1 读题

题目描述

两个或多个整数共有约数中最大的一个叫做它们的最大公约数。

两个或多个整数公有的倍数叫做它们的公倍数,其中除 0 0 0以外最小的一个公倍数就叫做这几个整数的最小公倍数。

现在有两个整数 a a a b b b( 2 ≤ a ≤ 100000 2≤a≤100000 2a100000 2 ≤ b ≤ 1000000 2≤b≤1000000 2b1000000),求出满足下列两个条件的所有 P P P Q Q Q的个数,条件:

1. P 1.P 1.P Q Q Q是正整数;

2. 2. 2.要求 P P P Q Q Q a a a为最大公约数,以 b b b为最小公倍数。

输入格式

输入一行,包含两个数 a a a b b b a a a b b b之间用空格隔开。

输出格式

输出一行,包含一个数,为满足条件的所有 P P P Q Q Q P P P Q Q Q为正整数)的个数,若不满足条件则个数为 0 0 0

输入样例

3 60

输出样例

4

样例说明

此时的 P P P Q Q Q分别为: [ 3 , 60 ] [3,60] [3,60] [ 12 , 15 ] [12,15] [12,15] [ 15 , 12 ] [15,12] [15,12] [ 60 , 3 ] [60,3] [60,3]

故答案为 4 4 4

数据范围与提示

对于 100 100% 100的数据, 2 ≤ a ≤ 100000 2≤a≤100000 2a100000 2 ≤ b ≤ 1000000 2≤b≤1000000 2b1000000

P a r t Part Part 2 2 2 思路

看到题目,我们就在想这个题需要求最大公约数,然后进行计算,这里我提供两种计算方法。

方法1:直接计算(常用,即辗转相除法)

int gcd(int a,int b){
    if(b==0)return a;
    return gcd(b,a%b);
}

方法2:使用 < n u m e r i c > <numeric> <numeric>库,自带 g c d gcd gcd(最大公约数)和 l c m lcm lcm(最小公倍数),(万能头有这个库)

#include<bits/stdc++.h>
using namespace std;
int main(){
	int a,b,gd,lm;
	cin>>a>>b;
	gd=gcd(a,b);
	lm=lcm(a,b);
	cout<<gd<<" "<<lm;
	return 0;
}

我们知道 l c m = a ÷ g c d × b lcm=a÷gcd\times b lcm=a÷gcd×b,这就相当于已知 l c m lcm lcm g c d gcd gcd,求 a a a b b b, 即 l c m × g c d = a × b lcm\times gcd=a\times b lcm×gcd=a×b

所以我们可以从 l c m lcm lcm开始一直枚举到 g c d gcd gcd,当 l c m × g c d % a lcm\times gcd\%a lcm×gcd%a不等于 0 0 0时(也就是说没有与 a a a对应的时候),我们直接跳过,否则我们建立一个变量 j = l c m × g c d ÷ a j=lcm\times gcd÷a j=lcm×gcd÷a,然后我们判断:如果 i i i j j j的最大公约数是 g c d gcd gcd,就可以加 1 1 1。也就是如下写法:

写法1

int m=a*b;//m就是两数乘积,即lcm*gcd
for(int i=a;i<=b;i++){
	if(m%i!=0)continue;//跳过环节
    int j=m/i;
	if(a==gcd(i,j))s++;//s是计数器
}

相比起写法1来说,我们可以更简单一些,也就是说不进行跳过环节,我们就得到了如下写法:

写法2(比起写法1来说更简明一些,省去了跳过环节)

for(int i=a;i<=b;i++)if((a*b)%i==0&&gcd(i,(a*b)/i)==a)s++;//s是计数器

小tip:大家可以先根据思路,写一下代码哦!

P a r t Part Part 3 3 3 代码

注意!!!以下部分我均采用方法1求 g c d gcd gcd,想使用方法2的自行上划

写法1

#include<bits/stdc++.h>
using namespace std;
int gcd(int a,int b){
    if(b==0)return a;
    return gcd(b,a%b);
}
int a,b,s;
int main(){
    cin>>a>>b;
    int m=a*b;
    for(int i=a;i<=b;i++){
	    if(m%i!=0)continue;
        int j=m/i;
	    if(a==gcd(i,j))s++;
    }
    cout<<s<<endl;
    return 0;
}

写法2

#include<bits/stdc++.h>
using namespace std;
int gcd(int a,int b){
    if(b==0)return a;
    return gcd(b,a%b);
}
int a,b,s;
int main(){
    cin>>a>>b;
    for(int i=a;i<=b;i++)if((a*b)%i==0&&gcd(i,(a*b)/i)==a)s++;
	//根据公式a/gcd*b=lcm可以推出
    cout<<s;
    return 0;
}

听完后,是不是觉得很简单呢?赶快自己去试一下吧!!!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值