题目
分析
让我们用这道题目来回顾一些数论中的基本概念。
最大公约数
如果\(a_1\),\(a_2\)是两个整数,而且\(d|a_1, d|a_2\)(或者写成\(a_1\%d=a_2\%d=0\)),那么\(d\)就是\(a_1\)和\(a_2\)的公约数。这样的d
可能有好几个,其中最大的那个就是“最大公约数”(Greatest Common Divisor,简称gcd
)。特别地,如果GCD(a, b)=1
,那么这两个数互质。
求两个数的gcd
有最完美的解法,也就是欧几里得发明的辗转相除法:
int gcd(int a, int b)
{
return b == 0 ? a : gcd(b, a % b);
}
最小公倍数
和gcd
对应的是“最小公倍数”(Least Common Multiple,简称lcm
)。求出gcd
后,可以这样求lcm
:\(LCM=(a\times b) / GCD\)。
GCD的一个重要性质
如果有很多数字,怎么求最大公约数呢?这里需要用到gcd
的一个重要性质:
对于\(a_1, a_2, ..., a_i, a_{i+1}, ..., a_n\)而言,如果它们的GCD是某个数,那么:
\(gcd(a_1, a_2, ..., a_i, a_{i+1}, ..., a_n)=gcd(gcd(a_1, a_2, ..., a_i), gcd(a_{i+1}, ..., a_n))\)
也就是说,在求多个数字的gcd
的时候,完全可以分组求出。
本题思路
回到本题,已经给出了gcd
(\(x_0\))和lcm
(\(y_0\)),要求一对数P/Q
,且\(gcd(P, Q)=x_0, lcm(P, Q)=y_0\)。
可见:
\( \begin{cases} P=gcd*a \\Q=gcd*b \\P\times Q=gcd*lcm \end{cases} \)
其中:\(gcd=x_0, lcm=y_0, gcd(a, b)=1\)。
由于求出P
后就能得到Q
,我们只要进行一个循环即可。考虑到P
的公式,我们循环的上限可以限制在\(m=y_0/x_0\)。为什么呢?因为对于a
来说,它的上限不会超过m
。证明如下:
\(\begin{align*} & P\times Q = gcd\times lcm = x_0\times y_0 \\ & P = gcd\times a, Q = gcd\times b \\ & P = x_0\times a, Q = x_0\times b \\ & x_0\times a\times x_0\times b = x_0\times y_0 \\ & \therefore a\times b = y_0/x_0 \end{align*}\)
我们找到了P
就知道了Q
,但在计数的时候要考虑一下两个数是否相等的问题。
答案
思考
这道题目不是很难,关键是确定a
的上限。