1 条题解
-
0
问题分析
我们需要找到最大的非负整数 ,使得 能被 整除。即:
这是一个经典的数论问题,涉及阶乘的质因数分解和整除性。
算法思路
核心思想:勒让德公式 + 质因数分解
利用勒让德公式计算 中每个质因数的指数,然后根据 的质因数分解来确定最大的 。
关键数学原理
-
质因数分解:将 分解为质因数的乘积
-
勒让德公式: 中质数 的指数为
$$v_p(n!) = \left\lfloor \frac{n}{p} \right\rfloor + \left\lfloor \frac{n}{p^2} \right\rfloor + \left\lfloor \frac{n}{p^3} \right\rfloor + \cdots $$ -
最大指数:对于每个质因数 , 中最多能提供 个 的因子
最终答案
$$x_{\text{max}} = \min_{1 \leq i \leq r} \left\lfloor \frac{v_{p_i}(n!)}{e_i} \right\rfloor $$代码详解
1. 主循环框架
for (; ~scanf("%lld%lld", &N, &K);) { ans = N; // 初始化答案为n,这是x的最大可能值 Int k = K; // 对k进行质因数分解 for (Int p = 2; p * p <= k; ++p) if (k % p == 0) { Int e = 0; // 计算质因数p的指数 do { ++e; k /= p; } while (k % p == 0); check(p, e); // 检查该质因数对答案的限制 } // 处理剩余的质因数(k本身是质数的情况) if (k > 1) { check(k, 1); } printf("%lld\n", ans); }2. 核心函数
checkvoid check(Int p, Int e) { Int val = 0; // 计算n!中质因数p的指数(勒让德公式) for (Int n = N; n /= p;) val += n; // 更新答案:取最小值 chmin(ans, val / e); }勒让德公式的实现技巧:
for (Int n = N; n /= p;) val += n;这等价于:
$$val = \left\lfloor \frac{N}{p} \right\rfloor + \left\lfloor \frac{N}{p^2} \right\rfloor + \left\lfloor \frac{N}{p^3} \right\rfloor + \cdots $$算法正确性
数学证明
设 ,那么:
能被 整除的充要条件是对于每个质因数 :
因此:
取最小值得到最大可能的 。
边界情况处理
- :题目保证
- :算法自然处理,答案可能为0
- 大数运算:使用
long long避免溢出
复杂度分析
时间复杂度
- 质因数分解:,由于 ,,可以接受
- 勒让德公式计算:对于每个质因数 ,需要 次除法
- 总复杂度:在数据范围内完全可行
空间复杂度
- :只需要常数个变量
算法优化
1. 质因数分解优化
- 只需要试除到
- 使用
p * p <= k避免浮点数运算
2. 勒让德公式计算优化
- 使用整数除法,避免浮点精度问题
- 循环
while (n /= p)简洁高效
3. 内存优化
- 不需要存储所有质因数,实时处理
总结
本题通过结合质因数分解和勒让德公式,优雅地解决了阶乘整除性问题。算法的核心优势在于:
- 数学严谨:基于数论经典公式
- 高效实现:复杂度在数据范围内完全可行
- 代码简洁:核心算法只有十几行代码
- 鲁棒性强:正确处理各种边界情况
该解法体现了数论知识在算法竞赛中的重要作用,展示了如何将数学理论转化为高效的程序实现。
-
- 1
信息
- ID
- 4991
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者