惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Security Archives - TechRepublic
Security Archives - TechRepublic
Project Zero
Project Zero
K
Kaspersky official blog
G
Google Developers Blog
T
Threat Research - Cisco Blogs
T
The Blog of Author Tim Ferriss
Cyberwarzone
Cyberwarzone
Y
Y Combinator Blog
Recorded Future
Recorded Future
Blog — PlanetScale
Blog — PlanetScale
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cisco Talos Blog
Cisco Talos Blog
Latest news
Latest news
Microsoft Security Blog
Microsoft Security Blog
H
Help Net Security
S
Schneier on Security
P
Palo Alto Networks Blog
H
Hacker News: Front Page
N
News and Events Feed by Topic
N
Netflix TechBlog - Medium
博客园 - Franky
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
SecWiki News
SecWiki News
Cloudbric
Cloudbric
TaoSecurity Blog
TaoSecurity Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
The Hacker News
The Hacker News
C
Check Point Blog
L
LangChain Blog
腾讯CDC
小众软件
小众软件
T
Tenable Blog
Google DeepMind News
Google DeepMind News
GbyAI
GbyAI
L
LINUX DO - 最新话题
A
About on SuperTechFans
Google Online Security Blog
Google Online Security Blog
C
Cisco Blogs
Recent Announcements
Recent Announcements
Hacker News: Ask HN
Hacker News: Ask HN
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Vercel News
Vercel News
雷峰网
雷峰网
美团技术团队
D
DataBreaches.Net
Martin Fowler
Martin Fowler
Help Net Security
Help Net Security
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
F
Full Disclosure
博客园_首页

博客园 - RonChen

同余分析 差分约束 Treap 点分治 莫队算法 分块 扫描线 错排问题 Sprague-Grundy (SG) 函数及其应用 容斥原理 卢卡斯定理 线性基 高斯消元 次短路 分层图最短路 01 图最短路 洪水填充 双向搜索 迭代加深搜索 剪枝 最小表示法 表达式计算 KMP 算法 队列 高精度运算
勒让德公式
RonChen · 2026-02-28 · via 博客园 - RonChen

当需要将 \(N!\) 分解为质因数的乘积时,直接计算阶乘再分解显然不现实,因为 \(N\) 稍大时结果就会巨大无比。勒让德公式提供了一种优雅的方法,可以直接计算出 \(N!\) 中每个质因子的指数,而不需要计算阶乘本身。

勒让德公式:对于任意质数 \(p\),阶乘 \(N!\) 中质因子 \(p\) 的指数 \(v_p(N!)\) 等于 \(v_p(N!) = \left\lfloor \dfrac{N}{p} \right\rfloor + \left\lfloor \dfrac{N}{p^2} \right\rfloor + \left\lfloor \dfrac{N}{p^3} \right\rfloor + \cdots = \sum \limits_{k=1}^{\infty} \left\lfloor \dfrac{N}{p^k} \right\rfloor\),这里 \(\lfloor x \rfloor\) 表示向下取整。

为什么这个公式成立?考虑从 \(1\)\(N\) 的所有整数,每个数都可能贡献若干个质因子 \(p\),逐层计算:

  • 首先,在 \(1, 2, \dots, N\) 中,能被 \(p\) 整除的数有 \(\lfloor N/p \rfloor\) 个,每个这样的数至少贡献一个 \(p\)
  • 其次,在这些数中,有些数还能被 \(p^2\) 整除,它们会额外再贡献一个 \(p\)(因为已经算过一次,所以第二次相当于补上一个 \(p\)),能被 \(p^2\) 整除的数有 \(\lfloor N/p^2 \rfloor\) 个。
  • 以此类推,能被 \(p^k\) 整除的数有 \(\lfloor N/p^k \rfloor\) 个,每个这样的数贡献了第 \(k\)\(p\)

因此,总指数就是所有 \(k\)\(\lfloor N/p^k \rfloor\) 之和。当 \(p^k \gt N\) 时,\(\lfloor N/p^k \rfloor = 0\),所以实际上只需计算到 \(p^k \le N\) 为止。

例题:P10495 阶乘分解

给定整数 \(N \ (3 \le N \le 10^6)\),要求将 \(N!\) 分解质因数,并按照算术基本定理的形式输出所有质因子 \(p_i\) 及其指数 \(c_i\)

只有 \(\le N\) 的质数才可能是 \(N!\) 的质因子,使用线性筛筛出所有可能的质因子。

对于筛出的每个质数 \(p_i\),应用勒让德公式计算其指数。

线性筛部分的时间复杂度为 \(O(N)\),而 \(N\) 以内质数个数约为 \(O(N/ \log N)\) 个,对于每个质数,只需要 \(O(\log N)\) 的时间计算,因此对整个 \(N!\) 分解质因数的时间复杂度为 \(O(N)\)

参考代码
#include <cstdio>
const int N = 1e6 + 5;
bool f[N];
int p[N], cnt;
void sieve(int n) {
    f[0] = f[1] = true;
    cnt = 0;
    for (int i = 2; i <= n; i++) {
        if (!f[i]) {
            p[cnt++] = i;
        }
        for (int j = 0; j < cnt && i * p[j] <= n; j++) {
            f[i * p[j]] = true;
            if (i % p[j] == 0) break;
        }
    }
}
int main()
{
    int n; scanf("%d", &n);
    sieve(n);
    for (int i = 0; i < cnt; i++) {
        int c = 0, t = p[i];
        // 使用循环累加每个 p^k 的倍数个数
        while (t <= n) {
            c += n / t;
            if (n / p[i] < t) break; // 防止溢出
            t *= p[i];
        }
        printf("%d %d\n", p[i], c);
    }
    return 0;
}