整数划分问题

整数划分是一个经典的问题。
Input
每组输入是两个整数n和k。(1 <= n <= 50, 1 <= k <= n)
Output
对于每组输入,请输出六行。
             第一行: 将n划分成若干正整数之和的划分数。
             第二行: 将n划分成k个正整数之和的划分数。 
             第三行: 将n划分成最大数不超过k的划分数。
             第四行: 将n划分成若干奇正整数之和的划分数。
             第五行: 将n划分成若干不同整数之和的划分数。
             第六行: 打印一个空行。

( 南开nodgd):全是递推题
I: f[i][j]表示i的划分为不超过j个数的划分数,此时分为两种情况: 包括i f[i-j][j]或者不包括i f[i][j-1]  
II: 初始化:i==1 或者j==1 时f[i][j]=1;
第一个f[i][j]表示i的划分为不超过j个数的划分数,f[i][j]=f[i-j][j]+f[i][j-1],最终输出f[N][N]。因为这个子问题元素可以多次使用所以递推的时候要用f[i-j][j]这个状态而不能用f[i-j][j-1]。写代码的时候外层循环j由小到大,内层循环i由小到大。
for(j=1;j<=N;j++)
f[0][j]=1;
for(j=1;j<=N;j++)
for(i=j;i<=N;i++)
f[i][j]=f[i-j][j]+f[i][j-1];
一维数组优化:
f[0]=1;
for(j=1;j<=N;j++)
for(i=j;i<=N;i++)//这个顺序每一个数可以取x次
f[i]+=f[i-j];

第二个f[i][j][k]表示把i划分成不超过j的k个数的划分数,f[i][j][k]=f[i-j][j][k-1]+f[i][j-1][k],输出f[N][N][K]。这个问题也是可以重复元素的,(如果不允许重复元素就用f[i][j][k]=f[i-j]

[j-1][k-1]+f[i][j-1][k])。写代码外层k由小到大,中层j由小到大,内层i由小到大。
for(j=0;j<=N;j++)
f[0][j][0]=1;
for(k=1;k<=K;k++)
for(j=1;j<=N;j++)
for(i=j;i<=N;i++)
f[i][j][k]=f[i-j][j][k-1]+f[i][j-1][k];
第三个递推同第一个,输出f[N][K]。

第四个f[i][j]表示把i划分成不超过j的奇数的划分数,f[i][j]=f[i-j][j]+f[i][j-2],递推循环时保证j是奇数,本质上和第一个相同。如果N是奇数输出f[N][N],N是偶数输出f[N][N-1]。(如果不允许重复元素就f[i][j]=f[i-j][j-2]+f[i][j-2]),外层循环j由小到大,内层i由小到大。

for(j=1;j<=N;j+=2)
f[0][j]=1;
for(j=1;j<=N;j+=2)
for(i=j;i<=N;i++)
f[i][j]=f[i-j][j]+f[i][j-2];

一维数组优化:

f[0]=1;
for(j=1;j<=N;j+=2)
for(i=1;i<=N;i++)
f[i]+=f[i-j];
第五个f[i][j]表示把i划分为不超过j的不同数的划分数,f[i][j]=f[i-j][j-1]+f[i][j-1]。外层循环j由小到大,内层i由小到大。显然对于每个i的分解,每个j都只被用了一次。

for(j=1;j<=N;j++)
f[0][j]=1;
for(j=1;j<=N;j++)
for(i=j;i<=N;i++)
f[i][j]=f[i-j][j-1]+f[i][j-1];

一维数组优化:

f[0]=1;
for(j=1;j<=N;j++)
for(i=N;i>=j;i--)//这个顺序代表j只能用一次,区分第一个
f[i]+=f[i-j];

注意:
(1)这些实际上都是简单的背包问题的变种,递推方法与背包问题类似。
(2)由于答案可能很大,可能涉及到高精度,但这不影响算法。
(3)以上递推都是最浅显易懂的写法,事实上除第二个以外都可以优化到用一维数组递推(省略[j]),而第二个可以优化到用二维数组递推(省略[k])

如果还有不能理解的可以草稿纸上写一下或者用程序把递推出的矩阵打出来看一下,应该就能明白了。

大概是:整数划分||DP||母函数||递推的更多相关文章

  1. [AHOI2009]中国象棋 DP,递推,组合数

    DP,递推,组合数 其实相当于就是一个递推推式子,然后要用到一点组合数的知识 一道很妙的题,因为不能互相攻击,所以任意行列不能有超过两个炮 首先令f[i][j][k]代表前i行,有j列为一个炮,有k列 ...

  2. 【NOI2019模拟2019.6.27】B (生成函数+整数划分dp|多项式exp)

    Description: \(1<=n,k<=1e5,mod~1e9+7\) 题解: 考虑最经典的排列dp,每次插入第\(i\)大的数,那么可以增加的逆序对个数是\(0-i-1\). 不难 ...

  3. UVa 926【简单dp,递推】

    UVa 926 题意:给定N*N的街道图和起始点,有些街道不能走,问从起点到终点有多少种走法. 很基础的dp.递推,但是有两个地方需要注意,在标记当前点某个方向不能走时,也要同时标记对应方向上的对应点 ...

  4. 2014北大研究生推免机试(校内)-复杂的整数划分(DP进阶)

    这是一道典型的整数划分题目,适合正在研究动态规划的同学练练手,但是和上一个随笔一样,我是在Coursera中评测通过的,没有找到适合的OJ有这一道题(找到的ACMer拜托告诉一声~),这道题考察得较全 ...

  5. HDU 5965 三维dp 或 递推

    题意:= =中文题 思路一:比赛时队友想的...然后我赛后想了一下想了个2维dp,但是在转移的时候,貌似出了点小问题...吧?然后就按照队友的思路又写了一遍. 定义dp[i][j][k],表示第i列, ...

  6. 51nod 1201 整数划分 dp

    1201 整数划分 基准时间限制:1 秒 空间限制:131072 KB   收藏  关注 将N分为若干个不同整数的和,有多少种不同的划分方式,例如:n = 6,{6} {1,5} {2,4} {1,2 ...

  7. 【BZOJ4944】【NOI2017】泳池 概率DP 常系数线性递推 特征多项式 多项式取模

    题目大意 有一个\(1001\times n\)的的网格,每个格子有\(q\)的概率是安全的,\(1-q\)的概率是危险的. 定义一个矩形是合法的当且仅当: 这个矩形中每个格子都是安全的 必须紧贴网格 ...

  8. [NOI2017]泳池——概率DP+线性递推

    [NOI2017]泳池 实在没有思路啊~~~ luogu题解 1.差分,转化成至多k的概率减去至多k-1的概率.这样就不用记录“有没有出现k”这个信息了 2.n是1e9,感觉要递推然后利用数列的加速技 ...

  9. bzoj 3612 [Heoi2014]平衡——整数划分(dp)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3612 因为力矩的缘故,变成了整数划分. 学习到了整数划分.就是那个图一样的套路.https: ...

随机推荐

  1. 到处是坑的微信公众号支付开发(java)

    之前公司项目开发中支付是用阿里的支付做的,那叫一个简单,随意:悲催的是,现在公司开发了微信公众号,所以我步入了全是坑的微信支付开发中... ------------------------------ ...

  2. ASP.NET Core Web服务器 Kestrel和Http.sys 特性详解

    ASP.NET Core Web服务器 Kestrel和Http.sys 特性详解 1.1. 名词解释 1.2. Kestrel基本工作原理 1.2.1. Kestrel的基本架构 1.2.2. Ke ...

  3. JAVA基础第一组(前5道题)

    1.[程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一 对兔子,假如兔子都不死,问每个月的兔子总数为多少?        1.程序分析: 兔 ...

  4. 201521123054《Java程序设计》第8周学习总结

    1. 本周学习总结 2. 书面作业 List中指定元素的删除(题目4-1) 1.1 实验总结 每次删除时下标需要-1:原理如图 统计文字中的单词数量并按出现次数排序(题目5-3) 2.1 伪代码(简单 ...

  5. 201521123035《Java程序设计》第七周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 参考资料: XMind 2. 书面作业 1.ArrayList代码分析 1.1 解释ArrayList的contains源代 ...

  6. Java程序设计第五周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 1.2 可选:使用常规方法总结其他上课内容. 2. 书面作业 **代码阅读:Child压缩包内源代码 Child.java源代 ...

  7. 学号:201521123116 《java程序设计》第五周学习总结

    1. 本章学习总结 2. 书面作业 1.代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误.并分析输出结果. 不能编 ...

  8. 201521123010 《Java程序设计》第3周学习总结

    1. 本周学习总结 2. 书面作业 1.代码阅读 public class Test1 { private int i = 1;//这行不能修改 private static int j = 2; p ...

  9. 控制结构(3) 状态机(state machine)

    // 上一篇:卫语句(guard clause) // 下一篇:局部化(localization) 基于语言提供的基本控制结构,更好地组织和表达程序,需要良好的控制结构. 前情回顾 上次分析了guar ...

  10. Linux Ubuntu jdk(环境变量)配置

    一.下载JDK - jdk版本建议是gz形式的,rpm是RedHat里面的命令,所以下载rpm格式的时候回遇到问题 二. 打开虚拟机,创建目录 1 创建目录 #mkdir home 2 转到该目录下 ...