题目描述
【问题描述】
定义阶乘 n! = 1 × 2 × 3 × · · · × n。
请问 100! (100 的阶乘)有多少个约数。
【运行限制】
• 最大运行时间:1s
• 最大运行内存: 128M
答案:39001250856960000
解题思路
【补充知识】
约数个数:
任意一个大于 1 的正整数 n 可以分解质因数:
n
=
p
1
α
1
×
p
2
α
2
×
…
×
p
k
α
k
n = p_1^{α_1} \times p_2^{α_2} \times…\times p_k^{α_k}
n=p1α1×p2α2×…×pkαk,
则n的约数的个数:
(
a
1
+
1
)
(
a
2
+
1
)
(
a
3
+
1
)
…
(
a
k
+
1
)
(a_1+1)(a_2+1)(a_3+1)…(a_k+1)
(a1+1)(a2+1)(a3+1)…(ak+1)。
定理简证:百度百科——约数个数定理
埃拉托色尼筛选法:
在自然数列中,寻找一定范围内质数的方法。先把1删除(1既不是质数也不是合数),然后不断地读取队列中当前未读的最小数n,然后把n的倍数删去,直到需求的范围内所有的数均删除或读取。
参考:百度百科——埃拉托色尼筛选法
【总体思路】
100! 是个158位的数,用暴力求出100!的约束不太科学。但我们可以先将1~100分别做因数分解,这些因数累乘起来,得到100!的因数分解。
2 = 2 1 2 = 2^1 2=21
…
44 = 2 2 × 11 44 = 2^2 \times 11 44=22×11
…
100 = 2 2 × 5 2 100 = 2^2 \times 5^2 100=22×52
⇔ \Leftrightarrow ⇔ 100 ! = 2 1 × . . . × 2 2 × 11 × . . . × 2 2 × 5 2 100! = 2^1\times...\times2^2 \times 11 \times...\times 2^2 \times 5^2 100!=21×...×22×11×...×22×52
整合成以下格式:
p
1
α
1
×
p
2
α
2
×
…
×
p
k
α
k
p_1^{α_1} \times p_2^{α_2} \times…\times p_k^{α_k}
p1α1×p2α2×…×pkαk,
则约数总数:
(
a
1
+
1
)
(
a
2
+
1
)
(
a
3
+
1
)
…
(
a
k
+
1
)
(a_1+1)(a_2+1)(a_3+1)…(a_k+1)
(a1+1)(a2+1)(a3+1)…(ak+1)
【代码思路】
1、对于
n
u
m
=
p
1
α
1
×
p
2
α
2
×
…
×
p
k
α
k
num = p_1^{α_1} \times p_2^{α_2} \times…\times p_k^{α_k}
num=p1α1×p2α2×…×pkαk ,将
p
i
p_i
pi、
a
i
a_i
ai 用数组arr存储,即arr[
p
i
p_i
pi ] =
a
i
a_i
ai。
2、由于结果会是一个比较大的数,那么res的数值范围必须足够大,所以这里将res的数值类型定义为 ‘long long’ 。
解题代码
C语言
#include <stdio.h>
int main(){
int arr[101] = {0};
int i, p, k;
long long res = 1;
// num=p1^a1*p2^a2*...*pn^an
// arr[pi]=ai,num能被pi除ai次
for(i=2; i<=100; i++){
int num = i;
for(p=2; p*p<=i; p++){ //将num因式分解
while(num%p==0){
++arr[p];
num /= p;
}
}
++arr[num];
}
//约数总数res=(a1+1)(a2+1)...(an+1)
for(k=2; k<=100; k++){
res *= arr[k] + 1;
}
printf("%lld",res);
return 0;
}