1 条题解
-
0
题目理解
定义 为从集合 中选出 个不同的数,并排成一个圆环(旋转视为相同)的不同方式数。
需要计算: $ S(n) = \sum_{i=1}^n \sum_{j=1}^i \big(C(i,j) \bmod j\big) $ 对 取模。
1. 推导 的公式
- 先从 个数中选 个: 种选法。
- 将选出的 个数排成圆环: 种排列(固定一个位置消除旋转)。
因此: $ C(i,k) = \binom{i}{k} \cdot (k-1)! = \frac{i!}{k \cdot (i-k)!} $
展开为:
分子是 个连续整数的乘积。
2. 化简
因为分子是 个连续整数,其中必有一个是 的倍数。具体来说,这个倍数是:
从分子中除去分母 后,该因子变成 ,而剩下的 个因子模 后恰好覆盖 各一次。
因此: $ C(i,j) \bmod j = \left( (j-1)! \times \left\lfloor \frac{i}{j} \right\rfloor \right) \bmod j $
3. 分情况讨论
情况 1: 是素数且
根据威尔逊定理,当 是素数时: 所以: $ C(i,j) \bmod j \equiv -\left\lfloor \frac{i}{j} \right\rfloor \pmod{j} $
情况 2: 是合数
对于合数 , 包含 的所有真因子,因此 ,所以:
但有一个特例:
,不是 ,需要单独处理。对于 : $ C(i,4) \bmod 4 = \left( 2 \times \left\lfloor \frac{i}{4} \right\rfloor \right) \bmod 4 $
4. 算法思路
我们需要计算: $ S(n) = \sum_{i=1}^n \sum_{j=1}^i \left[ C(i,j) \bmod j \right] $
直接双重循环不可行,因为 可达 , 可达 。
关键技巧:交换求和顺序
我们考虑所有满足 的数对 ,贡献为 。
固定 ,考虑所有 的贡献。对于每个 :
- 如果 是合数且 ,贡献为 。
- 如果 是素数,贡献为 。
- 如果 ,贡献为 。
因此,只有素数(和 )需要处理。
5. 使用差分数组优化
对于素数 ,我们要计算: $ \sum_{i=1}^n \sum_{j=1}^i [j=p] \cdot \left( -\left\lfloor \frac{i}{p} \right\rfloor \bmod p \right) $
设 ,其中 ,则 ,贡献为 (当 时)或 (当 时)。
具体地,对于固定的 ,考虑区间 内的所有 ,都有 ,贡献为 。
我们可以用差分数组
del来累加这些贡献:- 在 处加上
- 在 处减去
这样,对
del做前缀和,就能得到每个 处所有素数的贡献之和。对于 同理处理。
6. 最终计算
- 预处理所有素数(用埃氏筛)。
- 对每个素数 ,更新差分数组
del。 - 对 单独更新。
- 对
del做前缀和,得到每个 的贡献 。 - 再对 做前缀和,得到 。
- 输出 。
7. 复杂度分析
- 埃氏筛:
- 更新素数:每个素数 的循环次数约为 ,总和
- 总复杂度 ,可以处理 。
8. 代码对应解析
// 预处理素数 primes = eratosthenesSieve(MAX_N); vector<int> del(MAX_N, 0); // 处理所有素数 p for (auto &p: primes) { for (int curr = p; curr < MAX_N; curr += p) { int inc = (p - ((curr / p) % p)) % p; // (-k) mod p del[curr] = (del[curr] + inc) % MOD; if (curr + p < MAX_N) del[curr + p] = (del[curr + p] - inc + MOD) % MOD; } } // 处理 j = 4 的特例 for (int curr = 4; curr < MAX_N; curr += 4) { int inc = (2 * (curr / 4)) % 4; // 2 * floor(i/4) mod 4 del[curr] = (del[curr] + inc) % MOD; if (curr + 4 < MAX_N) del[curr + 4] = (del[curr + 4] - inc + MOD) % MOD; } // 前缀和得到 f(i) 和 S(n) int pref = 0; for (int i = 1; i < MAX_N; i++) { pref = (pref + del[i]) % MOD; // f(i) ans[i] = (ans[i - 1] + pref) % MOD; // S(i) }
9. 示例验证
以 为例:
- 素数 : 贡献 , 贡献
- 素数 : 贡献
- 合计 , ,
- ,与样例一致。
这样,我们就得到了一个高效的 解法。
- 1
信息
- ID
- 6203
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者