[NOI Online 2022 普及组] 数学游戏 - 题解
场外选手口胡题解
题目大意
- \(t\) 组数据,每组数据给定 \(x, z\),构造最小的 \(y\) 使得 \(z = x \times y \times \gcd(x, y)\),无解则输出 \(-1\)。
- \(1 \leq t \leq 5 \times 10^5\),\(1 \leq x \leq 10^9\),\(1 \leq z < 2^{63}\)。
解题思路
首先判无解。容易发现如果 \(z\) 不是 \(x\) 的倍数显然无解。
接下来我们将题目中所给的式子做第一步化简:
\[y \times \gcd(x, y) = \frac zx
\]
我们发现 \(\gcd(x, y)\) 不太方便化简,那就把它设出来吧。
不妨设 \(\gcd(x, y) = k\),\(x = k \times n\),\(y = k \times m\),我们有
\[(k \times m) \times k = k^2 \times m = \frac zx
\]
所以 \(k^2 \mid \frac zx\)。
考虑到 \(x = k \times n\),我们易得 \(k^2 \mid x^2\)。
\(\therefore k^2 \mid \gcd(x^2, \frac zx)\)
似乎有些进展不下去了。那我们来大胆的猜测:有没有可能这个 \(\gcd(x^2, \frac zx)\) 就恰好等于 \(k^2\) 呢?
推柿子,可以得到
\[\gcd(x^2, \frac zx) = \gcd((k \times n)^2, k \times y) = \gcd(k^2 \times n^2, k^2 \times m) = \gcd(n^2, m) \times k^2
\]
注意到 \(n, m\) 互质,所以 \(k^2 = \gcd(x^2, \frac zx)\),我们可以愉快地求出 \(k\) 啦!
当然,我们需要判断一下,如果 \(\gcd(x^2, \frac zx)\) 不是完全平方数则无解。
再次观察我们最初得到的式子,\(y \times \gcd(x, y) = \frac zx\)。
既然我们已经知道了 \(\frac zx\),知道了 \(k\) 也就是 \(\gcd(x, y)\),那么问题也迎刃而解了,
\[y = \frac zx \div \gcd(x, y) = \frac zx \div \sqrt{\gcd(x^2, \frac zx)}
\]
单次询问时间复杂度 \(O(1)\)。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int t, x, z, num;
int gcd(int a, int b) {
return (!b ? a : gcd(b, a%b));
}
inline int read() {
int x = 0; char ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) x = (x<<3) + (x<<1) + ch - '0', ch = getchar();
return x;
}
signed main() {
t = read();
while (t--) {
x = read(), z = read(), num = (int)sqrt(gcd(x*x, z/x));
if (z%x || num*num != gcd(x*x, z/x)) {
printf("-1\n");
continue;
}
printf("%lld\n", z/x/num);
}
}