蓝桥杯练习系统阶乘计算(Python)

问题描述

输入一个正整数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循环节省时间的地方就在于每次都用一个较大的数乘以个位数。
感谢万能的男朋友哈哈!

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值