1. 问题描述:
给定整数 N,试把阶乘 N! 分解质因数,按照算术基本定理的形式输出分解结果中的 pi 和 ci 即可。
输入格式
一个整数 N。
输出格式
N! 分解质因数后的结果,共若干行,每行一对 pi,ci,表示含有 pi ^ ci 项。按照 pi 从小到大的顺序输出。
数据范围
3 ≤ N ≤ 10 ^ 6
输入样例:
5
输出样例:
2 3
3 1
5 1
样例解释
5! = 120 = 2 ^ 3 ∗ 3 ∗ 5
来源:https://www.acwing.com/problem/content/199/
2. 思路分析:
这道题目非常经典,因为n最大为10 ^ 6所以不可能直接计算出来再分解,其中一种比较容易想到的方法是依次枚举当前的数字n,n - 1,...2,计算阶乘中每一个数字x的质因子出现的次数,但是这样做的时间复杂度为:n√n = 10 ^ 9肯定会超时的,所以不能够使用这种方法来解决,我们其实可以换一种枚举的顺序,可以先筛出当前1~n的所有质数,然后再枚举质因子出现的次数:
5! = 5 * 4 * 3 * 2 * 1,枚举n的质因子,对于质数p来说出现的次数为:⌊n / p⌋ + ⌊n / (p ^ 2)⌋ + ...,1~10^6大概有:10 ^ 6 / (log10^6) ≈ 50000,而对于所有质数p出现的次数为:log2 10^6 + log3 10 ^ 6 + .... ≈ 5000 * log2 10 ^ 6.
3. 代码如下:
from typing import List
class Solution:
count = 0
# 线性筛求解2~n的质数, 包括数字n
def init(self, n: int, primes: List[int], st: List[int]):
for i in range(2, n):
if st[i] == 0:
primes[self.count] = i
self.count += 1
j = 0
while primes[j] * i < n:
st[primes[j] * i] = 1
if i % primes[j] == 0:
break
j += 1
def process(self):
n = int(input())
self.count = 0
primes, st = [0] * (n + 10), [0] * (n + 10)
self.init(n + 1, primes, st)
for i in range(self.count):
p = primes[i]
j, s = n, 0
while j > 0:
s += j // p
j //= p
print(p, s)
if __name__ == '__main__':
Solution().process()