D. Storming Arasaka(Codeforces 2238)

D. Storming Arasaka

题意简述

给定一个整数 n。考虑 n 的所有正因子,除了 1 以外都要分到若干层 L_1, L_2, ..., L_k。

分层需要满足:

  1. 如果因子 x 在第 i 层,那么 x 的所有真因子,除了 1 和 x 自己以外,都必须出现在更早的层;
  2. 每一层里的数可以排成一个序列,使得相邻两个数的 gcd 都大于 1。

求最少需要多少层。

记号

设:

text 复制代码
n = p_1^{e_1} * p_2^{e_2} * ... * p_m^{e_m}

定义:

text 复制代码
Ω(n) = e_1 + e_2 + ... + e_m

表示质因子总个数,重复计算。

定义:

text 复制代码
ω(n) = m

表示不同质因子的个数。

本题答案是:

text 复制代码
Ω(n) + ω(n) - 1

为什么至少需要这么多层

1. 不同质数不能放在同一层

比如质数 2 和 3。

它们的 gcd(2, 3) = 1,不能相邻。

更重要的是,如果某层里有质数 p,那么这一层不能再有任何 p 的倍数。因为那些倍数的真因子包含 p,按规则必须放在更早的层。

所以含有质数 p 的层只能放 p 自己。

因此所有不同质数必须分别占用一层:

text 复制代码
至少需要 ω(n) 层来放这些质数

设最后出现的那个质数在第 L 层,那么一定有:

text 复制代码
L >= ω(n)

2. 从这个质数走到 n 还要继续往后放

假设最后出现的质数是 p。

从 p 开始,可以不断乘上剩余的质因子,形成一条因子链:

text 复制代码
p -> p * q_1 -> p * q_1 * q_2 -> ... -> n

这条链一共有 Ω(n) 个数。

因为后一个数以前一个数为真因子,所以它必须在更晚的层。

如果 p 在第 L 层,那么 n 至少要在:

text 复制代码
L + Ω(n) - 1

层。

又因为 L >= ω(n),所以:

text 复制代码
答案 >= Ω(n) + ω(n) - 1

为什么这么多层一定够

我们构造一种分层方法。

第一步,把所有不同质数分别单独放在前 ω(n) 层。

例如:

text 复制代码
L_1 = {p_1}
L_2 = {p_2}
...
L_m = {p_m}

第二步,从 s = 2 到 Ω(n),把所有满足下面条件的因子放进同一层:

text 复制代码
这个因子的质因子总个数正好是 s

也就是:

text 复制代码
第 m + s - 1 层:所有 Ω(x) = s 的因子 x

条件 1 为什么满足

如果 y 是 x 的真因子,那么:

text 复制代码
Ω(y) < Ω(x)

所以 y 一定在更早的层。

条件 2 为什么满足

同一层里所有数的质因子总个数都是同一个 s,并且 s >= 2。

可以把一个因子看成一个"质因子袋子"。

例如:

text 复制代码
12 = 2 * 2 * 3

就是袋子:

text 复制代码
[2, 2, 3]

同一层的袋子大小都相同。我们可以按一种类似 Gray Code 的顺序排列这些袋子:每次只替换一个质因子,保留其它 s - 1 个质因子。

因为 s >= 2,相邻两个袋子至少还共享一个质因子,所以对应两个数的 gcd > 1。

更直观地看:

text 复制代码
2*2*5  ->  2*3*5

它们都含有 2 和 5,所以 gcd > 1。

因此同一层可以排成符合要求的链。

于是总层数正好是:

text 复制代码
ω(n) + (Ω(n) - 1) = Ω(n) + ω(n) - 1

结合前面的下界,这就是最优答案。

例子

n = 120

分解:

text 复制代码
120 = 2^3 * 3^1 * 5^1

所以:

text 复制代码
Ω(120) = 3 + 1 + 1 = 5
ω(120) = 3

答案:

text 复制代码
5 + 3 - 1 = 7

一种分层示意:

层 内容
1 5
2 3
3 2
4 质因子总个数为 2 的因子
5 质因子总个数为 3 的因子
6 质因子总个数为 4 的因子
7 120

n = 2^5 = 32

text 复制代码
Ω(32) = 5
ω(32) = 1
答案 = 5 + 1 - 1 = 5

这和样例输出一致。

算法流程

  1. 预处理 1..10^6 每个数的最小质因子;
  2. 对每个测试用例分解 n;
  3. 统计:
    • totalPrimeFactors = Ω(n);
    • distinctPrimeFactors = ω(n);
  4. 输出:
text 复制代码
totalPrimeFactors + distinctPrimeFactors - 1

易错点

  1. Ω(n) 要重复计算质因子,例如 12 = 2^2 * 3,所以 Ω(12) = 3。
  2. ω(n) 只计算不同质因子,例如 12 的不同质因子是 2, 3,所以 ω(12) = 2。
  3. 答案不是约数个数,也不是最长整除链长度。最长整除链只给出 Ω(n),还要额外考虑不同质数不能在同一层。
  4. n 最大是 10^6,直接试除也可以,但预处理最小质因子更稳。

复杂度分析

预处理:

text 复制代码
时间复杂度:O(MAX log log MAX) 近似
空间复杂度:O(MAX)

每个测试用例分解:

text 复制代码
时间复杂度:O(log n)
空间复杂度:O(1)

其中 MAX = 10^6。

C++ 代码实现

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    const int MAX_N = 1'000'000;
    vector<int> spf(MAX_N + 1, 0); // smallest prime factor,最小质因子

    for (int i = 2; i <= MAX_N; ++i) {
        if (spf[i] == 0) {
            for (long long j = i; j <= MAX_N; j += i) {
                if (spf[j] == 0) {
                    spf[j] = i;
                }
            }
        }
    }

    int T;
    cin >> T;

    while (T--) {
        int n;
        cin >> n;

        int totalPrimeFactors = 0;    // Ω(n):质因子总个数,重复计算
        int distinctPrimeFactors = 0; // ω(n):不同质因子个数

        int x = n;
        while (x > 1) {
            int p = spf[x];
            ++distinctPrimeFactors;

            while (x % p == 0) {
                x /= p;
                ++totalPrimeFactors;
            }
        }

        cout << totalPrimeFactors + distinctPrimeFactors - 1 << '\n';
    }

    return 0;
}
相关推荐
落魄实习生几秒前
Agent Scope Java 2.x 系列【2】 ReActAgent
java·开发语言
山下梅子酒2256 分钟前
洛谷-入门-B2070
c语言
智鸟科技GemeOpen开发者智能设备10 分钟前
智能插座二次开发如何接入Home Assistant,从零开始完整工程实现(Python+React)
开发语言·python·物联网·react.js·智能家居
疯狂成瘾者11 分钟前
海康 Artemis 接口对接
开发语言·lua
Logic10121 分钟前
C语言/数据结构位运算题解:异或XOR找出多任务下载器中的“独特下载速度“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
2601_9622186122 分钟前
C++中decltype关键字的实现
开发语言·c++
hqyjzsb26 分钟前
法律 Prompt 干货:搭建合同审查提示词要包含哪些要素
开发语言·人工智能·python·职场和发展·数据分析·prompt·业界资讯
孙启超34 分钟前
【AI开发之Rust】第 19 课:UniFFI 导出核心能力
开发语言·后端·rust
Discipline10291 小时前
尼泊尔河流流量:天气驱动的预测与高流量风险
人工智能·算法
2601_966949651 小时前
股票池发生变化后,如何高效更新行情数据?从全量刷新到增量同步
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash