##[$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 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 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; } ```