P8255 [NOI Online 2022 普及组] 数学游戏(民间数据) 题解
简要题意:
给定 \(T\) 组 \(x,z\),求 \(\min{y} \space s.t. \space \space x \cdot y \cdot \gcd(x,y) = z\). 可能不存在。
\(T \leq 5 \times 10^5, x \leq 10^9, z < 2^{63}\).
很容易想到从质因数分解的角度入手。
不妨令对于某个素数 \(p\),\(x\) 含 \(a\) 个,\(y\) 含 \(b\) 个,\(\frac{z}{x}\) 含 \(c\) 个。我们试图已知 \(a,c\) 判断 \(b\). 那么:
分类讨论。
对于 \(c > 2a\) 的情况,此时必有 \(b > a\),即 \(b = c - a\).
对于 \(c \leq 2a\) 的情况,此时必有 \(b < a\),即 \(b = \frac{c}{2}\),但存在的条件是 \(c\) 为奇数。
到这里,我们暴力去模拟它,就可以得到一个 \(\mathcal{O}(T\sqrt{z})\) 的做法。但显然这是不优的。
如何快速判断是否存在?可以考虑取 \(r = \min(2a,c)\). 对于 \(c>2a\),一定存在,对应 \(r\) 一定为偶数;对于 \(c \leq 2a\),\(c\) 为偶数时存在,同样对应 \(r\) 为偶数。
也就是说,对于某个素数 \(p\),\(r = \min(2a,c) \equiv 0 \pmod 2\) 则在该素数上存在。
我们再从素因数倒推回去。取所有 \(p^r\) 的乘积,得到的结果就是 \(q = \gcd(x^2, \frac{z}{x})\). 而所有素数的指数为偶数则对应了 \(q\) 为完全平方数。
于是我们已经可以在 \(\mathcal{O}(\log z)\) 的时间内判断无解。
剩下来就很好办了。
\(r = \min(2a, c) = 2a\) 时 \(b = c-a\).
\(r = \min(2a, c) = c\) 时 \(b = \frac{c}{2}\).
考虑用一个式子直接表示 \(b\) 的值。很容易想到:
这个式子就是本题的真谛所在。由于 \(q\) 是完全平方数,那么此时 \(b\) 一定存在。而将所有 \(p^b\) 乘起来,就是题目所求的答案,整理化简之后也就是
时间复杂度:\(\mathcal{O}(T\log z)\).
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
int T; scanf("%d",&T);
while(T--) {
ll x, z; scanf("%lld %lld",&x,&z);
if(z % x) {puts("-1"); continue;}
z /= x;
ll p = __gcd(x * x, z);
ll q = sqrt(p);
if(q * q == p) printf("%lld\n", z / q);
else puts("-1");
}
}