问题描述
输入一个正整数n,输出n!的值。其中n!=123*…*n。
输入格式
输入包含一个正整数n,n<=1000。
输出格式
输出n!的准确值。
算法描述
n!可能很大,而计算机能表示的整数范围有限,需要使用高精度计算的方法。使用一个数组A来表示一个大整数a,A[0]表示a的个位,A[1]表示a的十位,依次类推。
将a乘以一个整数k变为将数组A的每一个元素都乘以k,请注意处理相应的进位。
首先将a设为1,然后乘2,乘3,当乘到n时,即得到了n!的值。
这篇博客把使用数组做阶乘的原理讲的很清楚,精华都在下面这张图中
阶乘计算(蓝桥杯)
参考代码
n=int(input())
c = 0 # 进位位
s = 1
# 初始化列表
# num_list列表的长度一定要大于1000的阶乘的位数
# 有些代码此处取range(10005) 但我在系统中运行以后显示超时
num_list = [0 for x in range(3000)]
num_list[0] = 1
# 这种方式可以指定位未知长度的列表
result = []
# 外层循环限制阶乘次数
for i in range(2,n+1):
#内层循环对每一位作阶乘
for j in range(3000):
s = num_list[j] * i + c
num_list[j] = s % 10
# 注意python中整数和普通除的区别
c = s // 10
# print(num_list)# 调试用代码
# 逆序输出
rnum_list = num_list[::-1]
for i in range(3000):
# 需要处理数组最高位没用到的0,但是要注意有些数的阶乘末尾有很多零
if rnum_list[i] == 0 and rnum_list[i+1] != 0:
# 记住有效数据位的下标
cnt = i
break
# print(cnt)# 调试用代码
for i in range(cnt, 3000):
#把有效数据位追加到结果列表中
result.append(rnum_list[i])
# 先把列表转换成字符串,再转换成整型打印输出
b = str(result).replace("[","").replace("]","").replace(",","").replace(" ","")
print(int(b))
# 调试用代码
# print(math.factorial(n))
# 使用库提供的阶乘函数验证结果需要在最开始加上import math
# if int(b) != math.factorial(n):
# print("错")
网上还有一种方法是用循环,没有按照题目给的算法思路来,但其实我挺不理解为什么没运行超时的
下面的代码参考
蓝桥杯每日一练:阶乘计算
n = int(input())
ans = 1
# range()左闭右开
for i in range(1, n + 1):
ans *= i
print(ans)
运行结果
从下往上数第一个错误是因为对官网给的算法理解有误,我总想着先把输入的整数转成字符串,在切片,对每位作阶乘
从下往上数第二个和第三个错误是没有考虑有些数的阶乘结果末尾有很多零,如果直接`if rnum_list[i] != 0 会把很多有效数据剔除掉
思考
一开始总想着拿到需要做阶乘的数之后,把个十百千位都提取出来,比如要求56437这个数的阶乘,那就定义一个数组a[0]=7,a[1]=3,a[2]=4
,a[3]=6,a[4]=5,那对7求阶乘结果是5040,怎么处理呢??思路上就不对!
然后看到参考代码之后请男朋友给自己讲了一下,明白了!
再回头看系统给的算法描述,首先将a设为1,然后乘2,乘3,当乘到n时,即得到了n!的值这句话就是精髓所在。
这种方法相较于直接使用for循环节省时间的地方就在于每次都用一个较大的数乘以个位数。
感谢万能的男朋友哈哈!