Files
python/TangDou/AcWing_TiGao/T5/FenJieZhiYinShu/197.md
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

111 lines
2.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

##[$AcWing$ $197$. 阶乘分解](https://www.acwing.com/problem/content/description/199/)
### 一、题目描述
给定整数 $N$,试把阶乘 $N!$ 分解质因数,按照算术基本定理的形式输出分解结果中的 $p_i$ 和 $c_i$ 即可。
**输入格式**
一个整数 $N$。
**输出格式**
$N!$ 分解质因数后的结果,共若干行,每行一对 $p_i,c_i$,表示含有 $p_i^{c_i}$ 项。按照 $p_i$ 从小到大的顺序输出。
**数据范围**
$3≤N≤10^6$
**输入样例**:
`5`
**输出样例**:
```cpp {.line-numbers}
2 3
3 1
5 1
```
**样例解释**
```cpp {.line-numbers}
5!=120=2^3∗3∗5
```
### 二、方法$1$
```cpp {.line-numbers}
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int n;
bool prime(int x) {
if (x == 2) return 1;
for (int i = 2; i * i <= x; i++)
if (x % i == 0) return 0;
return 1;
}
int main() {
cin >> n;
for (int i = 2; i <= n; i++) {
if (!prime(i)) continue;
LL x = i;
int ans = 0;
while (x <= n) ans += n / x, x *= i;
printf("%d %d\n", i, ans);
}
return 0;
}
```
### 三、方法$2$
1. 筛出$1 \sim n$的所有质数
2. 枚举每个质因子$x$,$n!$表示$1 * 2 * 3... * n$,从$1$到$n$中,求$x$的次数:
$$cnt(x)= \left \lfloor \frac{n}{x^1} \right \rfloor + \left \lfloor \frac{n}{x^2} \right \rfloor + \left \lfloor \frac{n}{x^3} \right \rfloor + ...$$
(直到$x$的次方大于$n$停止)
举栗子:
比如$10!=1\times 2\times 3\times 4\times 5\times 6\times 7\times 8\times 9\times 10$里有多少个$2$的倍数,
$$\large \left \lfloor \frac{n}{x^1} \right \rfloor = \frac{10}{2}=5$$
有多少个$4$的倍数
$$\large \left \lfloor \frac{n}{x^2} \right \rfloor = \frac{10}{4}=2$$
有多少个$8$的倍数
$$\large \left \lfloor \frac{n}{x^2} \right \rfloor = \frac{10}{8}=1$$
共$5+2+1=8$个,与例子对的上。
#### $Code$
```cpp {.line-numbers}
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
// 欧拉筛
const int N = 1e6 + 10;
int primes[N], cnt; // primes[]存储所有素数
bool st[N]; // st[x]存储x是否被筛掉
void get_primes(int n) {
memset(st, 0, sizeof st);
cnt = 0;
for (int i = 2; i <= n; i++) {
if (!st[i]) primes[cnt++] = i;
for (int j = 0; primes[j] * i <= n; j++) {
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
int main() {
int n;
cin >> n;
get_primes(n);
for (int i = 0; i < cnt; i++) {
int p = primes[i];
int s = 0;
// 思路:由大到小+除法降维
// 优点:不用考虑乘法而导致的爆int上限
for (int j = n; j; j /= p) s += j / p;
printf("%d %d\n", p, s);
}
return 0;
}
```