问题描述
将 3 分解成两个正整数的和,有两种分解方法,分别是 3 = 1 + 2 和 3 = 2 + 1。注意顺序不同算不同的方法。
将 5 分解成三个正整数的和,有 6 种分解方法,它们是 1+1+3 = 1+2+2 = 1+3+1 = 2+1+2 = 2+2+1 = 3+1+1。
请问,将 2021 分解成五个正整数的和,有多少种分解方法?
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。
本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
答案:691677274345
方法一:隔板法
整数拆分和排列组合息息相关
2021个球,有2020个位置,选取4个位置放板子,可以分成5个正整数的和C2020 取4 ,再定义阶乘算法
方法二:记忆化搜索(直接dfs跑不出来!)
题解:因为搜方案数,用dfs,为了优化,记忆化搜索+dfs,从后往前搜
f[k][n]:用前 k 个数凑出 n 的方案数
f=[[-1]*(2030) for i in range(10)]
def dfs(k,n):
if f[k][n]!=-1: return f[k][n]
if k==0:
if n==0 : return 1
else: return 0
f[k][n]=0
for i in range(1,n+1):
f[k][n] +=dfs(k-1,n-i)
return f[k][n]
print(dfs(5,2021))
凑数问题可以从完全背包的角度考虑,这里有5种物品,每种可以拿2021个,可以凑成2021(背包容量为2021)的方案数目,不是最大值,因此状态转移方程略有不同!
dp=[[0]*2030 for i in range(10)]#dp[k][n]代表用k个数凑n的方案数1 2 3 4 5 .....
for i in range(2022):
dp[1][i]=1
for i in range(2,6):#4种
for j in range(i,2022):#完全背包的写法
dp[i][j] =dp[i][j-1]+dp[i-1][j-1]#包括选第i种和不选凑j-1
print(dp[5][2021])
#for i in range(2022):
# print(dp[5][i])
P1036 [NOIP2002 普及组] 选数(dfs)
题目意思就是,从n个数选k个,看看凑成几,能凑成素数的方案数
import math
n,k=map(int,input().split())
num=list(map(int,input().split()))
num.insert(0,0)
#print(num)
def isPrime(x):
for i in range(2, int(math.sqrt(x) + 1)):
if x%i==0:
return 0
return 1
#就是一棵搜索树!
def dfs(start,summ,rem):
ans=0
if rem==0:
#print(isPrime(summ))
return isPrime(summ)
for i in range(start+1,n+1):
ans +=dfs(i,summ+num[i],rem-1)#ans相当于搜索树的结点, 储存情况的种数, 然后向上汇总
return ans
print(dfs(0,0,k))#从1开始, 还剩n个, 所选数总数