题目描述
给定整数 N N N ,试把阶乘 N ! N! N! 分解质因数,按照算术基本定理的形式输出分解结果中的 p i p_i pi 和 c i c_i ci即可。
输入格式
一个整数N。
输出格式
N ! N! N!分解质因数后的结果,共若干行,每行一对 p i , c i p_i,c_i pi,ci,表示含有 p i c i p_i^{c_i} pici项。按照 p i p_i pi从小到大的顺序输出。
数据范围
1 ≤ N ≤ 1 0 6 1≤N≤10^6 1≤N≤106
输入样例
5
输出样例
2 3
3 1
5 1
样例解释
5 ! = 120 = 2 3 × 3 × 5 5!=120=2^3\times3\times5 5!=120=23×3×5
基础硬件
题解
算法1:暴力 O ( n ) O(n) O(n)(空间爆炸)
把
n
n
n的阶乘算出来,然后质因数分解
n
>
20
n>20
n>20就直接炸掉
果断白给
code
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
int n;
long long p[maxn],c[maxn];
void zhiyinshufenjie(unsigned long long n)
{
long long m=0;
for(long long i=2;i<=sqrt(n);i++)
{
if(n%i==0)
{
p[++m]=i;
while(n%i==0) n/=i,c[m]++;
}
}
if(n>1)
{
p[++m]=n;
c[m]++;
}
for(int i=1;i<=m;i++) cout<<p[i]<<' '<<c[i]<<endl;
}
int main()
{
cin>>n;
unsigned long long k=1;
for(int i=1;i<=n;i++)
k*=i;
zhiyinshufenjie(k);
return 0;
}
算法2:稍微不那么暴力 O ( n × n ) O(n\times \sqrt n) O(n×n)
把
1
−
n
1-n
1−n的每个数质因子分解,再把结果合并
能抗到
n
=
1
0
5
n=10^5
n=105左右了
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
int c[maxn],n;//c用来统计指数出现次数
void zhiyinshufenjie(int n)
{
for(int i=2;i<=sqrt(n);i++)
if(n%i==0)
while(n%i==0) n/=i,c[i]++;
if(n>1) c[n]++;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
zhiyinshufenjie(i);
for(int i=1;i<=n;i++) if(c[i]) cout<<i<<' '<<c[i]<<endl;
return 0;
}
算法3:正解 O ( n × l o g n ) O(n\times log n) O(n×logn)
n
!
n!
n!中质因子
p
p
p的个数就等于
1
−
n
1-n
1−n每个数包含质因子
p
p
p的个数之和。在
1
−
n
1-n
1−n中,
p
p
p的倍数,即至少包含
1
1
1个质因子
p
p
p(即
1
−
n
1-n
1−n中
p
p
p的倍数)有
⌊
n
/
p
⌋
\lfloor n/p \rfloor
⌊n/p⌋个。而
p
2
p^2
p2的倍数,即至少包含
2
2
2个质因子
p
p
p的有
⌊
n
/
p
2
⌋
\lfloor n/p^2 \rfloor
⌊n/p2⌋个。不过其中的
1
1
1个质因子已经在
⌊
n
/
p
⌋
\lfloor n/p \rfloor
⌊n/p⌋里统计过,所以只需要再统计第
2
2
2个质因子,即累加上
⌊
n
/
p
2
⌋
\lfloor n/p^2 \rfloor
⌊n/p2⌋个,而不是
2
×
⌊
n
/
p
2
⌋
2\times\lfloor n/p^2 \rfloor
2×⌊n/p2⌋个
For example:
对于
n
=
4
n=4
n=4,
p
=
2
p=2
p=2而言
1
−
n
1-n
1−n中包含2(
⌊
n
/
p
⌋
\lfloor n/p \rfloor
⌊n/p⌋)个数是
p
p
p的倍数,即2和4,
再来统计
⌊
n
/
p
2
⌋
\lfloor n/p^2 \rfloor
⌊n/p2⌋,只有
4
4
4符合条件,按道理来讲,既然前面是
p
2
p^2
p2,那么计数器是不是应该加
2
2
2呢?
并不是这样,在统计
p
p
p的时候,就已经将
4
4
4的其中
1
1
1个质因子
2
2
2统计过了,所以计数器只需要加
1
1
1,而不需要加
2
2
2
综上所述,
n
!
n!
n!中质因子p的个数为
⌊
n
p
⌋
+
⌊
n
p
2
⌋
+
⌊
n
p
3
⌋
+
⋯
+
⌊
n
p
⌊
l
o
g
p
∗
n
⌋
⌋
=
∑
p
k
≤
n
⌊
n
p
k
⌋
\lfloor\frac{n}{p}\rfloor+\lfloor\frac{n}{p^2}\rfloor+\lfloor\frac{n}{p^3}\rfloor+\dots+\lfloor\frac{n}{p^{\lfloor log_p*n\rfloor}}\rfloor=\sum_{p^k\leq n}\lfloor\frac{n}{p^k}\rfloor
⌊pn⌋+⌊p2n⌋+⌊p3n⌋+⋯+⌊p⌊logp∗n⌋n⌋=∑pk≤n⌊pkn⌋
code
#include<bits/stdc++.h>
using namespace std;
bool vis[1000100];
int c[1000100],p[1000100];
int main()
{
int n,m=0;
scanf("%d",&n);
for(int i=2;i<=n;i++) //埃式筛求质数
if(!vis[i])
{
c[++m]=i;
for(int j=i*2;j<=n;j+=i)
vis[j]=1;
}
for(int i=1;i<=m;i++)//遍历质数
for(int k=1;;k++)
if(pow(c[i],k)>n) break;//当超出n的范围,就退出循环
else p[i]+=n/(pow(c[i],k));//如上述讲解中的公式
for(int i=1;i<=m;i++)
if(p[i])
printf("%d %d\n",c[i],p[i]);
return 0;
}