1 条题解
-
0
题目描述
给定一个正整数 ,求能被 内所有数整除的最小数字(即最小公倍数 ),并对 取模。
输入格式
一行一个整数 。输出格式
一行一个整数,表示答案。样例
输入:10输出:
2520数据范围
算法思路
1. 问题分析
我们需要计算: 根据数论知识,最小公倍数可以表示为所有质数幂的乘积: $ \text{LCM}(1,2,\dots,n) = \prod_{p \ \text{prime}} p^{e_p} $ 其中 是满足 的最大整数。
2. 关键观察
对于每个质数 ,我们需要找到最大的 使得 ,然后将 乘到答案中。
原理
- 必须包含足够的质因子幂次,以覆盖 到 中所有数的质因数分解
- 对于质数 , 以内 的最高次幂就是
- 这样才能确保所有 的倍数、平方倍数等都被覆盖
3. 算法步骤
- 使用线性筛法找出所有不超过 的质数
- 对每个质数 ,计算 的最大
- 将所有这样的 相乘,并对 取模
- 输出结果
4. 复杂度分析
- 时间复杂度:
- 线性筛法时间复杂度为
- 每个质数求幂次的时间可以忽略
- 空间复杂度:
- 需要数组标记合数和存储质数
对于 ,该算法在时间和空间上都是可行的。
代码实现
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define N 100000003 #define MX 10000 #define LL long long #define p 100000007 using namespace std; bool pd[N]; int n, prime[6000000]; int main() { scanf("%d", &n); LL ans = 1; for (int i = 2; i <= n; i++) { if (!pd[i]) { // i是质数 prime[++prime[0]] = i; LL t = i; // 找到不超过n的最大p的幂 while (t * (LL)i <= n) t *= i; ans = ans * t % p; } for (int j = 1; j <= prime[0]; j++) { int k = i * prime[j]; if (k > n) break; pd[k] = 1; // 标记合数 if (i % prime[j] == 0) break; // 保证每个合数被最小质因子筛掉 } } printf("%lld\n", ans); return 0; }
样例验证
以 为例:
- 质数 :
- 质数 :
- 质数 :
- 质数 :
乘积:,与样例输出一致。
总结
本题的关键在于:
- 理解 的质因数分解形式
- 使用线性筛法高效枚举所有质数
- 对每个质数取不超过 的最高次幂
- 将所有质数幂相乘得到最终结果
该解法充分利用了数论性质,在线性时间内解决了问题,能够高效处理 的大数据范围。
- 1
信息
- ID
- 3926
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者