整数分解【第十二届】【省赛】【B组】Python 【整数拆分——隔板法、dfs+记忆化搜索(减枝) 、完全背包问题变式】

本文探讨了两种解决将整数分解为正整数和的方法,即隔板法和记忆化搜索。通过举例展示了如何计算将2021分解为五个正整数之和的不同方法数量,最终得出答案为691677274345。这两种方法分别涉及排列组合和动态规划策略,对于优化大规模问题的求解提供了思路。
摘要由CSDN通过智能技术生成

问题描述
将 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个, 所选数总数 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值