1 条题解
-
0
思路与算法
记 。原式通分得到 ,移项为
因为 都为正且原式成立,必有 。于是对 的每个正因数 ,令 ,恰得一组正整数解。题目计有序对,不能再除以2。
若 ,则 的约数个数为 。无需构造巨大阶乘。用埃氏筛枚举 ,通过
$$e_p=\lfloor n/p\rfloor+\lfloor n/p^2\rfloor+\cdots$$计算它在 中的指数。程序从 开始反复整除 并累加,避免显式连乘 。最后把各项乘积对 取模。 时质因子表为空,空积为1,对应解 。
正确性说明
通分和配方对正数等价。由 可知 ,同理 ,所以两个移位量均为正。映射 把原式的每个有序解对应到 的一个正因数;反向构造也是正整数解,且互为逆映射,因此解数正是因数个数。
一个素数 的倍数对阶乘提供一次 , 的倍数再提供一次,依此类推,逐层计数恰得指数公式。唯一分解保证平方后每个素数指数为 ,每个因数独立选取指数0至 ,共有 种。逐步取模保持乘积余数,所以输出为所求解数模数值。
复杂度
初始化筛数组为 ,埃氏筛为 (小规模可写 )。指数累加精确需 ,给出简单总上界 。筛数组占 ,其余仅常数变量,总额外空间 。不生成 或所有解。
易错点
- 有顺序,样例的 与 都计入。
- 求的是阶乘平方的因数个数,所以使用 ,不是 。
- 用反复整除求指数,不显式算巨大阶乘或不断乘素数幂。
- 每次模乘前用64位;本范围指数不超过 ,因子与模内结果之积小于64位上界。
- 覆盖 、小质数、最大值及接近上界的质数。独立答案按2至n逐个分解累加,未把参考程序同一指数循环当独立验证。
参考代码(C++11)
#include <bits/stdc++.h> using namespace std; using ll = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<bool> bad(n + 1); ll result = 1; for (int p = 2; p <= n; p++) if (!bad[p]) { if (p <= n / p) for (int k = p * p; k <= n; k += p) bad[k] = true; ll exponent = 0; for (int v = n; v;) { v /= p; exponent += v; } result = result * (2 * exponent + 1) % 1000000007; } cout << result << '\n'; }
- 1