题目描述
输入两个正整数 x 0 , y 0 x_0, y_0 x0,y0,求出满足下列条件的 P , Q P, Q P,Q 的个数:
- P , Q P,Q P,Q 是正整数。
- 要求 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 种:
- 3 , 60 3,60 3,60。
- 15 , 12 15,12 15,12。
- 12 , 15 12,15 12,15。
- 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 2≤x0,y0≤105 。
思路
题意应该很明确,就是找一对数,使它们的最小公约数是
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 ]
意思就是,两个数的最大公约数和最小公倍数的积就是这两个数的积
可以这样来理解:
这样的话
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 k∣x 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;
}