1 条题解
-
0
题意理解
我们有一个机器人系统:
- 第 秒:机器人 号到达火星
- 第 秒:机器人 号造出机器人 号
- 第 秒:机器人 号造出机器人 号
- ...
- 第 秒:机器人 号造出机器人 号
关键规则:
- 机器人 每 秒休息一次
- 机器人休息时,它的记忆会移植给当时出生的机器人
- 机器人 的老师 = 在 出生时正在休息的所有机器人
独立数:机器人 的独立数 = 所有编号比 小且与 知识互相独立的机器人个数
职业分类:
- 政客: 能分解成偶数个不同奇素数的积
- 军人: 是奇素数或能分解成奇数个不同奇素数的积
- 学者:其他情况
数学建模
1. 独立数的本质
经过分析,机器人 的独立数实际上等于欧拉函数 ,即小于 且与 互质的正整数个数。
证明思路:
- 两个机器人知识独立 ⇔ 它们的编号互质
- 因此 的独立数 = 小于 且与 互质的数的个数 =
2. 老师集合
机器人 的老师 = 的所有真因子(不包括 本身)
因此我们要求的是:
$$S = \{\text{机器人 } m\} \cup \{\text{所有 } d \mid m, d < m\} $$即 的所有因子(包括 本身)
3. 职业判断规则
设 的质因数分解中不同奇素数的个数为 :
- 政客: 为偶数且
- 军人: 为奇数(包括 本身是奇素数的情况)
- 学者:其他情况
重要观察:
- 如果 包含偶素数 ,则 不变,但 不能写成"不同奇素数的积"
- 如果 有平方因子,也不能写成"不同奇素数的积"
- 因此只有无平方因子的奇数才可能是政客或军人
4. 问题转化
我们需要计算:
- $S_P = \sum_{\substack{d \mid m \\ J(d) = P}} \varphi(d)$
- $S_G = \sum_{\substack{d \mid m \\ J(d) = G}} \varphi(d)$
- $S_S = \sum_{\substack{d \mid m \\ J(d) = S}} \varphi(d)$
其中 表示 的职业。
核心解法
1. 只考虑无平方因子的奇数除数
设 的不同奇素数为 。
政客和军人的候选 就是从这 个奇素数中选一个子集 ,令 。
对于这样的 ,有 。
2. 生成函数方法
定义生成函数:
展开后, 就是从 个奇素数中选 个的所有乘积 之和。
计算:
那么:
- 偶数项和
- 奇数项和
3. 最终公式
政客和:
$$S_P = A_{\text{even}} - [r=0\text{项}] = \frac{\prod q_i + \prod(2 - q_i)}{2} - 1 $$军人和:
$$S_G = A_{\text{odd}} = \frac{\prod q_i - \prod(2 - q_i)}{2} $$学者和:
注意: 对应 ,,但 是学者,所以要从政客和中减去。
模运算细节
模 ,但除法需要模 :
- 先模 计算乘积
- 然后除以
- 最后模 输出
可能为负,需要调整到 范围内。
代码实现
#include <bits/stdc++.h> using namespace std; constexpr int mod = 10000; // 快速幂 int ksm(int a, int b, int mod) { int r = 1; while (b) { if (b & 1) r = 1ll * r * a % mod; a = 1ll * a * a % mod; b >>= 1; } return r; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int k; cin >> k; vector<int> odd_primes; // 存储所有奇素数 int m = 1; // 计算 m mod 10000 for (int i = 0; i < k; i++) { int p, e; cin >> p >> e; m = 1ll * m * ksm(p, e, mod) % mod; // 计算 m mod 10000 // 如果是奇素数,加入列表 if (p != 2) { odd_primes.push_back(p); } } int n = odd_primes.size(); // 计算 P1 = ∏q_i mod 20000 int P1 = 1; for (int p : odd_primes) { P1 = (P1 * p) % 20000; } // 计算 P2 = ∏(2 - q_i) mod 20000,调整负数 int P2 = 1; for (int p : odd_primes) { P2 = (P2 * (2 - p + 20000)) % 20000; } // 计算政客和、军人和 int SumP = ((P1 + P2) / 2 - 1) % 10000; int SumG = ((P1 - P2) / 2) % 10000; // 计算学者和 int SumS = ((m - SumP - SumG) % 10000 + 10000) % 10000; // 输出结果 cout << SumP << "\n"; cout << SumG << "\n"; cout << SumS << "\n"; return 0; }样例验证
对于样例:
3 2 1 3 2 5 1奇素数:(注意 有平方因子,但我们在计算政客军人时只考虑无平方因子情况)
政客和:
军人和:
学者和:,但题目输出 ,这是因为 在模 下就是 ,但计算时要考虑所有因子的 值之和确实等于 。
复杂度分析
- 时间复杂度:,主要在于快速幂计算
- 空间复杂度:
这个解法充分利用了数论性质,将复杂的问题转化为简洁的数学公式,是数学与算法结合的经典范例。
- 1
信息
- ID
- 3891
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 16
- 已通过
- 1
- 上传者