Acwing-197. 阶乘分解
本蒟蒻的第一篇题解,还请多多点评qwq.
------------------------------------------分割线------------------------------------------
Part1:
看到这道题的第一眼,你想到了什么?
Part1.1-思路
将一个数进行质因数分解,复杂度是多少?如果我们分两种最好最坏的情况来讨论,
那分别应该是 \(O(logN)\) 和 \(O(N)\) 的。为什么?对于一个数,如果他是二的幂次,
那么在枚举到质因子 2 时,程序就已经可以宣布 去世 结束了。
反之,如果 \(N\) 是一个质数,那么程序枚举就会一直枚举到 \(N\) 时,才会结束。
所以,这个解法就是正解了吗?就...一个一个数分解就过了?
Part1.2-证明
分两种情况讨论。第一种,假设所有的数分解都需要 \(O(N)\) 的复杂度,
那么总共的时间就变化为了 \(O(\sum_{i = 1}^{i \le N}i)\) .凡是拿过计算器的都知道这
肯定会TLE的.那么 \(O(logN)\) 呢?虽然 \(O(NlogN)\) 可以勉强通过,但
事实上,并不是所有的数分解的复杂度都是 \(O(logN)\) 的。
结合以上证明,我们能很明确地确定这种解法是无解的。
------------------------------------------分割线------------------------------------------
Part2正解&代码:
在讲正解前,先看一段表格:
| \(N!\) | 拆出多少个 \(2^1\) | \(2^2\) | \(2^3\) | \(2^4\) |
|---|---|---|---|---|
| 10 | 5个 | 2个 | 1个 | 0个 |
| 30 | 15个 | 7个 | 3个 | 1个 |
看完这个表格,你有什么启发?
-
7 = 30 / 4 = 30 / \(2^2\).
-
15 = 30 / 2 = 30 / \(2^1\).
-
3 = 30 / 8 = 30 / \(2^3\).
对于一个质因子 \(i\) ,他在对 \(N!\) 进行质因数分解时出现的个数为:
不过要枚举到无穷是不可能的,所以当 \(N/i^j\) 等于0时,就应停止循环.
那么现在,搞定了单个质因子,如何确认有哪些质因子呢?
换句话说,如何确认有哪些质数呢?
很简单,利用质数筛法即可。用埃氏筛法或线性筛都可以,因为 \(N\) 只有 \(10^6\),所以没有任何问题。
所以,将 \(N!\) 进行质因数分解,输出每一个质因子分解的个数,公式为:
其中, \(P\) 为质数集合(prime).
结合以上结论,亮出最终的代码:
#include<bits/stdc++.h>
using namespace std;
int n,prime[1000005],num,cnt;
bool n_prime[1000005];
int main(){
ios::sync_with_stdio(false);//加快输入速度
cin >> n;
for(int i = 2;i <= n;i++){
if(!n_prime[i]){prime[num] = i;num++;}
for(int j = 0;j < num;j++){
if(prime[j] * i > n) break;//以免筛的过程中越界
n_prime[prime[j] * i] = true;
if(i % prime[j] == 0) break;
}
}
for(int i = 0;i < num && prime[i] <= n;i++){
cnt = 0;
for(int j = 1;pow(prime[i],j) <= n;j++){
cnt += n / pow(prime[i],j);
}
if(!cnt) break;
cout<<prime[i]<<" "<<cnt<<'\n';
}
//有关质数筛法的进一步了解,可以去看“http://oiwiki.com/math/number-theory/sieve/”这个网址.
return 0;
}
小蒟蒻第一次写题解,点个关注吧qwq,谢谢!

浙公网安备 33010602011771号