1 条题解
-
0
题目大意
给定一个整数 (),判断是否能找到三个不同的整数 ,满足 且 。若存在,输出任意一组;否则输出
"NO"。
解题思路
假设我们按升序排列 。
为了尽可能让 小,我们首先寻找 的最小因子(大于 ),记为 。
然后,在去掉 之后,剩余部分为 。接下来,我们寻找 的最小因子,且该因子不能等于 也不能是 ,记为 。
最后,令 。
如果 也满足 且 且 (由构造过程自动满足 因为 是 的最小非 非 的因子),则得到一组解;否则无解。
算法步骤
- 对每个测试用例的 :
- 寻找 的最小真因子 ()。若 是质数,则不存在这样的 ,直接输出
"NO"。 - 令 。
- 寻找 的最小因子 ,满足 且 。若不存在这样的 ,则输出
"NO"。 - 令 。检查 是否满足 且 且 。若满足,则输出
"YES"和 ;否则输出"NO"。
- 寻找 的最小真因子 ()。若 是质数,则不存在这样的 ,直接输出
正确性说明
- 由于 是 的最小因子(),任何其他因子都 。
- 同理, 是 的最小因子且不等于 ,保证了 且 ,因此 。
- 最后 ,因为 是 的最小非 非 的因子,所以 ,并且若 则意味着 ,此时 是唯一因子,但我们已经要求 ,且 ,所以 不可能等于 或 (除非 ,但此时 ,且 是 的最小因子,则 时 是最小因子,那么 ,最小因子 可能等于 ,但被排除,因此若 没有其他因子则无解,这符合逻辑)。因此 自动满足。
- 若这样的 存在,它们必然互不相同且 ,即为合法解。
时间复杂度
寻找一个数的因子需要 的试除。对于每个测试用例,我们最多进行两次这样的查找(一次找 ,一次找 ),因此总复杂度 ,在 且 时足够快。
代码实现(C++)
#include <bits/stdc++.h> using namespace std; int main() { int t; cin >> t; while (t--) { int n; cin >> n; // 寻找 a:n 的最小因子(>1) int a = -1; for (int i = 2; i * i <= n; ++i) { if (n % i == 0) { a = i; break; } } if (a == -1) { // n 是质数 cout << "NO\n"; continue; } int m = n / a; // 寻找 b:m 的最小因子(>1 且不等于 a) int b = -1; for (int i = 2; i * i <= m; ++i) { if (m % i == 0 && i != a) { b = i; break; } } // 注意:b 可能来自 i 或 m/i,需要检查两个方向 if (b == -1) { // 检查 m 本身是否满足(即 b = m 的情况,但要保证 m != a 且 m >= 2) if (m != a && m >= 2) { b = m; } } if (b == -1 || b == a) { cout << "NO\n"; continue; } int c = m / b; if (c >= 2 && c != a && c != b) { cout << "YES\n" << a << " " << b << " " << c << "\n"; } else { cout << "NO\n"; } } return 0; }
示例解析
以 为例:
- 最小因子 ,。
- 的最小因子()为 (因为 已被占用),。
均 且互不相同,乘积为 ,输出"YES 2 4 8"。
以 为例:
- ,。
- 的最小因子()为 (注意 不行),。但 ,不满足互异,故无解。
以 为例:质数,直接输出
"NO"。
总结
本题的关键是贪心地取最小可能的 和 ,然后检查剩余的 是否合法。这种方法避免了枚举所有因子组合,保证了 的效率。
- 对每个测试用例的 :
- 1
信息
- ID
- 6474
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者