【蓝桥杯】 阶乘约数:定义n的阶乘= 1 × 2 × 3 × · · · × n。 请问100 的阶乘有多少个约数。

【蓝桥杯】 阶乘约数

  • 题目描述
  • 解题思路
  • 解题代码
    • C语言

题目描述

题目传送门 >> 阶乘约数

【问题描述】
定义阶乘 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 

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;
}

你可能感兴趣的:(#,蓝桥杯,算法,1024程序员节,蓝桥杯,c语言)