洛谷P1029最大公约数和最小公倍数问题题解--zhengjun

题目描述

输入两个正整数 x 0 , y 0 x_0, y_0 x0,y0,求出满足下列条件的 P , Q P, Q P,Q 的个数:

  1. P , Q P,Q P,Q 是正整数。
  2. 要求 P , Q P, Q P,Q x 0 x_0 x0 为最大公约数,以 y 0 y_0 y0 为最小公倍数。

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

输入格式

一行两个正整数 x 0 , y 0 x_0, y_0 x0,y0

输出格式

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

输入输出样例
输入 #1 复制
3 60
输出 #1 复制
4
说明/提示

P , Q P,Q P,Q 4 4 4 种:

  1. 3 , 60 3,60 3,60
  2. 15 , 12 15,12 15,12
  3. 12 , 15 12,15 12,15
  4. 60 , 3 60,3 60,3

对于 100 % 100\% 100% 的数据, 2 ≤ x 0 , y 0 ≤ 10 5 2 \le x_0, y_0 \le {10}^5 2x0,y0105

思路

题意应该很明确,就是找一对数,使它们的最小公约数是 x 0 x_0 x0 ,最大公倍数是 y 0 y_0 y0
然后,还有一点,就是小学数学(我已经初一了)里面的一个公式:

x × y = (   x , y   ) × [   x , y   ] x\times y=(\ x,y\ )\times [\ x,y\ ] x×y=( x,y )×[ x,y ]

意思就是,两个数的最大公约数和最小公倍数的积就是这两个数的积

可以这样来理解:
A_zjzj

这样的话

x × y = x\times y= x×y= ( ( ( × \times × ) ) ) × \times × ( ( ( × \times × ) ) )

(   n , m   ) × [   n , m   ] = (\ n,m\ )\times [\ n,m\ ]= ( n,m )×[ n,m ]= × \times × ( ( ( × \times × × \times × ) ) )

这样就可以理解了,所以,只要枚举一个数,另一个数就可以算出来。

然后,求最大公约数还有一种很快的方法:辗转相除法

比如说求 391 391 391 527 527 527 的最大公约数:
      ∣ 391     527 ∣ \ \ \ \ \ |391\ \ \ 527|      391   527
   0   ∣ 0         391 ∣   1   ‾ \underline{\ \ 0\ |0\ \ \ \ \ \ \ 391|\ 1\ }   0 0       391 1 
      ∣ 391     136 ∣ \ \ \ \ \ |391\ \ \ 136|      391   136
   2   ∣ 272     119 ∣   1   ‾ \underline{\ \ 2\ |272\ \ \ 119|\ 1\ }   2 272   119 1 
      ∣ 119      17 ∣ \ \ \ \ \ |119\ \ \ \ 17|      119    17
   7   ∣ 119          ∣      ‾ \underline{\ \ 7\ |119\ \ \ \ \ \ \ \ |\ \ \ \ }   7 119            
      ∣ 0             ∣ \ \ \ \ \ |0\ \ \ \ \ \ \ \ \ \ \ |      0           

这样除到 0 0 0 为止

证明:

假设 x x x , y y y 的最大公约数就是 k k k

k ∣ x   m o d   y k|x\ mod\ y kx mod y,问题就转换成了求 y y y x   m o d   y x\ mod\ y x mod y 的最大公约数

以此类推,无论怎么模,余数始终是 k k k 的倍数,这样一步步算下来,最后当余数为 0 0 0 时, x x x 就是这两个数的最大公约数

这样,所有问题就都解决了

代码

#include<bits/stdc++.h>
using namespace std;
int m,n,ans;
int zj(int x,int y)//不要在意这个函数名
{
	int z;
    while(y!=0){//辗转相除法
    	z=x%y;
    	x=y;
    	y=z;
	}
	return x;
}
int main()
{
    cin>>n>>m;
    for(register int i=n;i<=m;i++)//因为P,Q一定比最大公约数大,比最小公倍数小
        if(n*m%i==0&&zj(i,n*m/i)==n)//符合要求
		    ans++;
    cout<<ans;
    return 0;
}

谢谢–zhengjun

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A_zjzj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值