網站首頁 編程語言 正文
求N的階乘
本題要求編寫程序,計算N的階乘。
輸入格式:
輸入在一行中給出一個正整數 N。
輸出格式:
在一行中按照“product = F”的格式輸出階乘的值F,請注意等號的左右各有一個空格。題目保證計算結果不超過雙精度范圍。
輸入樣例:
5
輸出樣例:
product = 120
x = int(input())
a = 1
for i in range(1, x+1):
? ? a = a*i
print("product = %d" % float(a))
實現階乘的三種解法
問題描述:
輸入一個正整數n,輸出n!的值。
其中n!=123*…*n。
算法描述:
n!可能很大,而計算機能表示的整數范圍有限,需要使用高精度計算的方法。使用一個數組A來表示一個大整數a,A[0]表示a的個位,A[1]表示a的十位,依次類推。
將a乘以一個整數k變為將數組A的每一個元素都乘以k,請注意處理相應的進位。
首先將a設為1,然后乘2,乘3,當乘到n時,即得到了n!的值。
輸入格式:
輸入包含一個正整數n,n<=1000。
輸出格式:
輸出n!的準確值。
樣例輸入:
10
樣例輸出:
3628800
看到這題我首先想到的是兩種比較簡單的解法,一是循環,二是遞歸。
解法一:循環
n = int(input())
ns = 1
for i in range(1,n+1):
? ? ns = ns*i
print(ns)
思路比較簡單,就是定義一個變量ns賦予一個初始值1,然后利用for循環直接累乘得到最終結果。
解法二:遞歸
def factorial(n):
? ? if n==1:
? ? ? ? return n
? ? else:
? ? ? ? return n*factorial(n-1)
n = int(input())
res = factorial(n)
print(res)
遞歸也比較好理解,當n == 2,return 2 * 1;n == 3,return 3*(2 * 1);n==4,return 4*(3*(2*1))。以此類推,再將最終的結果賦予res將其打印即可。
這兩種方法都比較簡單,但很顯然都不符合題目要求的 “使用一個數組A來表示一個大整數a,A[0]表示a的個位,A[1]表示a的十位”,所以我們要想辦法利用數組來得到n!的結果。
解法三:數組
n= int(input())
ns = [0 for i in range(10000) ]
length = 1
ns[0] = length = 1
if n>=2:
? ? for i in range(2,n+1):
? ? ? ? carry = 0
? ? ? ? for j in range(length):
? ? ? ? ? ? temp = ns[j] * i + carry
? ? ? ? ? ? carry = int(temp/10)
? ? ? ? ? ? ns[j] = temp % 10
? ? ? ? while carry>0:
? ? ? ? ? ? ns[length] += carry%10
? ? ? ? ? ? length+=1
? ? ? ? ? ? carry = int(carry/10)
while length>0:
? ? length -=1
? ? print(ns[length],end='')
接下來我講下思路:
首先定義一個ns數組用來存儲n!的各個位數上的數值,利用for循環給ns加入10000個0值,以方便后面直接根據index對數組進行操作。
然后定義length作為 “數組的長度”(有真實數值的而非自動添加的0) 也即n!的結果的位數。
之后也必須用到for循環進行累乘,但跟解法一的直接累乘不同,這里是乘數(即i)跟各個位上的數分別相乘,若結果大于等于10則carry>0即向前進一位數值為carry,若j循環結束后carry>0則說明需要在當前ns的“長度”上進一位,所以length+1即位數+1,這里carry起的就是判斷是否進位的作用,而length則代表著結果的位數。可能這么說有些抽象,下面我們通過分解運行過程來更直觀的闡述上面的想法。
例如我們現在需要求5!,分五步,即i循環5次:
①i=1
?? ?ns[0] = length =1 , carry = 0
?? ?∴j in range(1)
⑴ j=0
?? ?temp = ns[j] * i + carry = ns[0] * i + carry =1*1+0=1 ?# temp為第j位數與i相乘并加上j-1位數與i相乘后進位的值的結果
?? ?carry = int(temp/10) = 1/10 = 0 ??? ?# carry=0所以不用進位
?? ?ns[j] = temp % 10 即 ns[0] = 1 % 10 =1 ? #只取個位數值作為第j位的值
②i=2
?? ?ns[0] = 1, length =1 , carry = 0
?? ?∴j in range(1)
⑴ j=0
?? ?temp = ns[j] * i + carry = ns[0] * i + carry =1*2+0=2 ?# temp為第j位數與i相乘并加上j-1位數與i相乘后進位的值的結果
?? ?carry = int(temp/10) = 2 / 10 = 0 ??? ?# carry=0所以不用進位
?? ?ns[j] = temp % 10 即 ns[0] = 2 % 10 =2 ? #只取個位數值作為第j位的值
?? ?#這樣就已經的到2!的值了即2
③i=3
?? ?ns[0] = 2, length =1 , carry = 0
?? ?∴j in range(1)
⑴ j=0
?? ?temp = ns[j] * i + carry = ns[0] * i + carry =2*3+0=6 ?# temp為第j位數與i相乘并加上j-1位數與i相乘后進位的值的結果
?? ?carry = int(temp/10) = 6 / 10 = 0 ??? ?# carry=0所以不用進位
?? ?ns[j] = temp % 10 即 ns[0] = 6 % 10 =6 ? #只取個位數值作為第j位的值
?? ?#這樣就已經的到3!的值了即6
④i=4
?? ?ns[0] = 6, length =1 , carry = 0
?? ?∴j in range(1)
⑴ j=0
?? ?temp = ns[j] * i + carry = ns[0] * i + carry =6*4+0=24 ?# temp為第j位數與i相乘并加上j-1位數與i相乘后進位的值的結果
?? ?carry = int(temp/10) = 24 / 10 = 2 ??? ?# carry=2>0所以需要向前進2
?? ?ns[j] = temp % 10 即 ns[0] = 24 % 10 =4 ? #只取個位數值作為第j位的值
j循環結束,carry>0執行while循環
?? ?while carry>0:?? ??? ?
?? ??? ? ? ?ns[length] += carry%10 即 ns[1] += 2 % 10 = 2 ?#carry = 2 所以向前進2
? ? ? ? ? ? length+=1 即 length =1+1=2 #位數加一
? ? ? ? ? ? carry = int(carry/10) = 2 / 10 = 0 # carry = 2<10所以不需要繼續進位,while循環結束
? ? ? ? ? ? ∴length = 2 , ns[0] = 4 ,ns[1] = 2
? ? #這樣就得到4!的值ns[1]*10+ns[0] 即 24,輸出時可直接倒著打印然后end=''而不需要每位數乘10*n再相加
⑤i=5
? ? ns[0] = 4, ns[1] = 2 length =2 , carry = 0
?? ?∴j in range(2)
⑴ j=0
?? ?temp = ns[j] * i + carry = ns[0] * i + carry =4*5+0=20 ?# temp為第j位數與i相乘并加上j-1位數與i相乘后進位的值的結果
?? ?carry = int(temp/10) = 20 / 10 = 2 ??? ?# carry=2>0所以需要向前進2
?? ?ns[j] = temp % 10 即 ns[0] = 20 % 10 =0 ? #只取個位數值作為第j位的值
⑵ j=1
? ? temp = ns[j] * i + carry = ns[1] * i + carry =2*5+2=12 ?# temp為第j位數與i相乘并加上j-1位數與i相乘后進位的值的結果
?? ?carry = int(temp/10) = 12 / 10 = 1 ??? ?# carry=1>0所以需要向前進1
?? ?ns[j] = temp % 10 即 ns[1] = 12 % 10 =2 ? #只取個位數值作為第j位的值
j循環結束,carry>0執行while循環
?? ?while carry>0:?? ??? ?
?? ??? ? ? ?ns[length] += carry%10 即 ns[2] += 1 % 10 = 1 ?#carry = 1 所以向前進2
? ? ? ? ? ? length+=1 即 length =2 +1 = 3 #位數加一
? ? ? ? ? ? carry = int(carry/10) = 1 / 10 = 0 # carry = 1<10所以不需要繼續進位,while循環結束
? ? ? ? ? ? ∴length = 3 , ns[0] = 0 , ns[1] = 2 , ns[2] = 1
? ? # 這樣就得到5!的值ns[2] ns[1] ns[0]即 120
這樣看下來是否發現和小學的時候學的豎式乘法運算過程很相似,從低位數到高位數(ns[j],j in range(0,length))依次與乘數(i)相乘,大于十則進位(carry=temp/10>0,若ns[length]*i+carry > 10則length+1)。
原文鏈接:https://blog.csdn.net/sinat_28502161/article/details/86531416
相關推薦
- 2022-07-21 數據庫慢查詢介紹并優化
- 2023-03-01 Shell腳本read用法實現_linux shell
- 2022-09-23 Android?如何獲取傳感器的數據方法詳解_Android
- 2022-06-07 C語言非遞歸算法解決快速排序與歸并排序產生的棧溢出_C 語言
- 2022-07-12 jmm內存模型及volatile實現原理
- 2022-09-06 詳解pygame中Rect對象_python
- 2022-10-28 一文帶你了解Python列表生成式應用的八重境界_python
- 2022-06-11 python中Event實現線程間同步介紹_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支