1 条题解

  • 0
    @ 2026-4-10 16:40:36

    题目大意

    给定一个整数 nn2n1092 \le n \le 10^9),判断是否能找到三个不同的整数 a,b,ca, b, c,满足 2a,b,c2 \le a, b, cabc=na \cdot b \cdot c = n。若存在,输出任意一组;否则输出 "NO"


    解题思路

    假设我们按升序排列 a<b<ca < b < c
    为了尽可能让 aa 小,我们首先寻找 nn 的最小因子(大于 11),记为 aa
    然后,在去掉 aa 之后,剩余部分为 n/an / a。接下来,我们寻找 n/an / a 的最小因子,且该因子不能等于 aa 也不能是 11,记为 bb
    最后,令 c=n/(ab)c = n / (a \cdot b)
    如果 cc 也满足 c2c \ge 2cac \neq acbc \neq b(由构造过程自动满足 c>bc > b 因为 bbn/an/a 的最小非 11aa 的因子),则得到一组解;否则无解。


    算法步骤

    1. 对每个测试用例的 nn
      • 寻找 nn 的最小真因子 aaa2a \ge 2)。若 nn 是质数,则不存在这样的 aa,直接输出 "NO"
      • m=n/am = n / a
      • 寻找 mm 的最小因子 bb,满足 b2b \ge 2bab \neq a。若不存在这样的 bb,则输出 "NO"
      • c=m/bc = m / b。检查 cc 是否满足 c2c \ge 2cac \neq acbc \neq b。若满足,则输出 "YES"a,b,ca, b, c;否则输出 "NO"

    正确性说明

    • 由于 aann 的最小因子(>1>1),任何其他因子都 a\ge a
    • 同理,bbmm 的最小因子且不等于 aa,保证了 bab \ge abab \neq a,因此 b>ab > a
    • 最后 c=m/bc = m / b,因为 bbmm 的最小非 11aa 的因子,所以 cbc \ge b,并且若 c=bc = b 则意味着 m=b2m = b^2,此时 bb 是唯一因子,但我们已经要求 bab \neq a,且 aba \neq b,所以 cc 不可能等于 bbaa(除非 a=b=ca = b = c,但此时 n=a3n = a^3,且 aann 的最小因子,则 n=a3n = a^3aa 是最小因子,那么 m=a2m = a^2,最小因子 bb 可能等于 aa,但被排除,因此若 a2a^2 没有其他因子则无解,这符合逻辑)。因此 c>bc > b 自动满足。
    • 若这样的 a,b,ca, b, c 存在,它们必然互不相同且 2\ge 2,即为合法解。

    时间复杂度

    寻找一个数的因子需要 O(n)O(\sqrt{n}) 的试除。对于每个测试用例,我们最多进行两次这样的查找(一次找 aa,一次找 bb),因此总复杂度 O(tn)O(t \cdot \sqrt{n}),在 t100t \le 100n109n \le 10^9 时足够快。


    代码实现(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;
    }
    

    示例解析

    n=64n = 64 为例:

    • 最小因子 a=2a = 2m=32m = 32
    • mm 的最小因子(a\neq a)为 b=4b = 4(因为 22 已被占用),c=32/4=8c = 32 / 4 = 8
      a=2,b=4,c=8a=2, b=4, c=82\ge 2 且互不相同,乘积为 6464,输出 "YES 2 4 8"

    n=32n = 32 为例:

    • a=2a = 2m=16m = 16
    • mm 的最小因子(a\neq a)为 b=4b = 4(注意 22 不行),c=16/4=4c = 16 / 4 = 4。但 c=bc = b,不满足互异,故无解。

    n=97n = 97 为例:质数,直接输出 "NO"


    总结

    本题的关键是贪心地取最小可能的 aabb,然后检查剩余的 cc 是否合法。这种方法避免了枚举所有因子组合,保证了 O(n)O(\sqrt{n}) 的效率。

    • 1

    信息

    ID
    6474
    时间
    1000ms
    内存
    256MiB
    难度
    6
    标签
    递交数
    1
    已通过
    1
    上传者