將整數n,劃分為m個整數的和(1≤
m≤n)
(1 \le m \le n)
(1≤m≤n
),求有多少種加法結果。
聯想到抽屜原理
容易得出,兩種極端情況。
m =n
m = n
m=n,抽屜數等於item個數,這意味著只有一種分法
m =1
m = 1
m=1,只有乙個抽屜,怎麼分都也是只有一種分法
那麼,就剩下一種最一般的情況了。
n
>
mn > m
n>
m, 抽屜的個數小於item個數
思路:先給每個抽屜都派乙個item,盈餘的item數surplus為n−m
n - m
n−m,
然後,將surplus按照其公因數分配到抽屜中(那麼k個公因數也就有k種抽屜分配情況),構造出所有的抽屜,再計算所有抽屜的組合數之和,即計算結果。
from itertools import permutations
# 計算排列組合個數
defcombines
(_set)
:return
len(
set(permutations(_set,
len(_set)))
)def
get_cnt
(_desk, _num)
:if _num <
0or _desk <0:
return
0if _desk ==
1or _desk == _num:
# 兩種特殊的情況
return
1 cnt =
0# 累計當前所有排列可能
surplus = _num - _desk # 給每個抽屜分配乙個item後的盈餘的個數
shares =
(x for x in
range(1
, surplus +1)
if surplus <= x * _desk)
# 盈餘個數的可劃分份數集
# 根據每次放入不同的份數,構造不同的抽屜
for x in shares:
tmp = surplus
drawers =[1
]* _desk # 生成抽屜並向每個抽屜放入乙個item
index =
0while tmp >0:
if tmp < x:
# 剩餘的盈餘數少於單份放入抽屜的數量
drawers[index]
+= tmp
tmp =
0else
: drawers[index]
+= x
tmp -= x
index +=
1 cnt += combines(drawers)
# 計算序列組合數
return cnt
defsolution()
: cnt =
0 n =
int(
input
("請輸入整數n:"))
for i in
range(1
, n +1)
: cnt += get_cnt(i, n)
return cnt
print
(solution(
))
將乙個整數劃分為多個正整數之和
整數劃分問題是將乙個正整數n拆分成一組數連加並等於n的形式,顯然這組數中最大加數不大於n。令n為需要劃分的整數,m為劃分後的最大整數。例如將6劃分為最大加數為6的劃分形式如下 5 1 4 2,4 1 1 3 3,3 2 1,3 1 1 1 2 2 2,2 2 1 1,2 1 1 1 1 1 1 1 ...
將乙個整數劃分為多個正整數之和
整數劃分問題是將乙個正整數n拆分成一組數連加並等於n的形式,顯然這組數中最大加數不大於n。令n為需要劃分的整數,m為劃分後的最大整數。例如將6劃分為最大加數為6的劃分形式如下 65 1 4 2,4 1 1 3 3,3 2 1,3 1 1 1 2 2 2,2 2 1 1,2 1 1 1 1 1 1 1...
基本演算法 拆分為連續正整數之和
整數拆分 即把乙個給定的正整數拆分為若干個連續正整數之和 例如 將輸入乙個整數15,可以拆分為 15 1 2 3 4 5 15 4 5 6 15 7 8 分析 由題可知,拆分的起始項i不會超過該數n的一半減一 1 n 1 2 累加項不會超過該數的一半加一 i n 1 2 這裡可以作為迴圈的條件,在j...