分析:
如果直接采取普通的分解质因数的方法,那么由于有n个数相乘,普通分解质因数的时间复杂度是O(sqrt(n)),总的时间复杂度是O(Nsqrt(n)) 会超时
思考有没有其他办法可以筛选质因数呢?逆向思维一下,可以从质因数的角度出发,看看n!里面还有多少个这个数
规律:
我们发现,对于1~n来说,假设质因数是p
- 1~n中只是p的倍数,拥有1个p
- 1~n中是p^2的倍数,拥有2个p
- ...
那么,从质因数的角度出发,我们只需要找出1~n中有多少个p的倍数就可以了,可想而知是[n/p](下取整),可以表示出有多少个p个倍数,但是p^k有k个p,此时还有k-1个没有被记下来,重复
[n/p^2]...就可以来保证记录下质因数p所有的个数
基本的思想是:因为p的倍数和p^(2~k)倍数的集合是重复的,所以对于重复的集合是不能重复计算,每次只加上一次就可以了
#include <iostream>
#include <algorithm>
using namespace std;
const int N=1e6+10;
int primes[N];
bool st[N];
int cnt;
void solve(int n)
{
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;
solve(n);
for(int i=0;i<cnt;i++)
{
int p=primes[i];
int s=0;
for(int j=n;j;j/=p) s+=j/p; //枚举p^(1~k),由于集合重复,所以每次只加上一次
cout<<p<<' '<<s<<endl;
}
return 0;
}