【noi 2.6_8787】数的划分(DP){附【转】整数划分的解题方法}
题意:问把整数N分成K份的分法数。(与“放苹果”不同,在这题不可以有一份为空,但可以类比)
解法:f[i][j]表示把i分成j份的方案数。
f[i][j]=f[i-1][j-1](新开一份,放1)
而i≥j时,f[i][j]=f[i-1][j-1] +f[i-j][j](不新开一份时的方案数与每份中都少放1的方案数相同)
一种更好的解释——方法可以分为两类:
1. n 份中不包含 1 的分法,为保证每份都 >= 2,可以先拿出 k 个 1 分。到每一份,然后再把剩下的 n- k 分成 k 份即可,分法有: dp[n-k][k]
2. n 份中至少有一份为 1 的分法,可以先那出一个 1 作为单独的1份,剩下的 n- 1 再分成 k- 1 份即可,分法有:dp[n-1][k-1]
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std; int f[210][10];
int main()
{
int n,k;
scanf("%d%d",&n,&k);
memset(f,0,sizeof(f));
for (int i=1;i<=n;i++) f[i][1]=1;
for (int i=1;i<=n;i++)
for (int j=2;j<=k;j++)
if (j<=i)
f[i][j]=f[i-1][j-1]+f[i-j][j];
printf("%d",f[n][k]);
return 0;
}
附——整数划分的解题方法
{Article 1 转自——http://blog.csdn.net/luke2834/article/details/49429353 ; Article 2 转自——http://blog.csdn.net/athenaer/article/details/8265234}
其中一些问题具体实现见我另外几篇博文——http://www.cnblogs.com/konjak/p/6004018.html & http://www.cnblogs.com/konjak/p/6004636.html
我略修改了一下原博文,大家可比较一下。Article 1的方法很特别,Article 2的思路常规但也挺重要的。
问题描述:给定一个正整数N和K
1.
将n划分成若干正整数之和的划分数。
2.将n划分成k个正整数之和的划分数。
3.将n划分成最大数不超过k的划分数。
4.将n划分成若干奇正整数之和的划分数。
5.将n划分成若干不同整数之和的划分数。
Article 1:总的来说这些都是背包问题;
第一个问,就是一个完全背包,背包有 1 --- N 种,第 i 种背包的重量为 i ,价值为 i ;这很好解决:
1 dp[0] = 1;
2 for (i = 1;i <= N;i++)
3 for (j = i;j <= N;j++)
4 dp[j] += dp[j-i];
其中 dp[j] 是用前 i 个数能构成 j 的种类数,则结果就为 dp[N]
看完这个问题了,那么 第3个问就知道了 , 即用前 K 种背包来装 所得结果,只需把第一层循环的 i <= N 改为 i <= K 即可;
1 dp[0] = 1;
2 for (i = 1;i <= K;i++)
3 for (j = i;j <= N;j++)
4 p[j] += dp[j-i];
那么第四个问呢,想想是奇数,那么 i = 2,4,6,…… 等等值就不能取了,因为这些背包种类不合要求,这很简单啊 i++ 改为 i += 2 不就行了;
1 dp[0] = 1;
2 for (i = 1;i <= N;i+=2)
3 for (j = i;j <= N;j++)
4 dp[j] += dp[j-i];
再看看第五个问,若干个不同的???想到了什么,就是一种背包最多只能用一次???这是什么,经典的 01背包 啊,与第一个问的不同就是第二层循环的顺序而已;
1 dp[0] = 1;
2 for (i = 1;i <= N;i++)
3 for (j = n;j >= i ;j--)
4 dp[j] += dp[j-i];
最后我们来思考第二个问:要求只要 K 个,这怎么办呢???想想特殊情况…… 如果 K = 1 呢,只能是 N 咯,若果 N = 0 呢, 结果只能是 0 种可能啊,那同样N < K 的话,不可能分啊。结果为 0 ,好,特殊的考虑完了,那么我们再考虑,分的结果中有没有 1 。 如果有1,那么就把剩下的 N - 1 分成 K - 1 份 ; 如果没有呢,那么我们先拿出 K 份 给每一堆 一个1, 再把剩下的 N - K 分成 K 份就行了。
Article 2:整数划分 --- 一个老生长谈的问题:
1.将n划分成不大于m的划分法: P.S.依问题定义——不定义划分成多少份。
1).若是划分多个整数可以存在相同的:
dp[n][m]= dp[n][m-1]+ dp[n-m][m] dp[n][m]表示整数 n 的划分中,每个数不大于 m 的划分数。
分两种情况:
a.划分中每个数都小于 m,相当于每个数不大于 m- 1, 故划分数为 dp[n][m-1].
b.划分中有一个数为 m. 那就在 n中减去 m ,剩下的就相当于把 n-m 进行划分, 故划分数为 dp[n-m][m];
2).若是划分多个不同的整数:
dp[n][m]= dp[n][m-1]+ dp[n-m][m-1] dp[n][m]表示整数 n 的划分中,每个数不大于 m 的划分数。
分两种情况:
a.划分中每个数都小于m,相当于每个数不大于 m-1,划分数为 dp[n][m-1].
b.划分中有一个数为 m.在n中减去m,剩下相当对n-m进行划分,
并且每一个数不大于m-1,故划分数为 dp[n-m][m-1]
2.将n划分成k个数的划分法:
dp[n][k]= dp[n-k][k]+ dp[n-1][k-1];
方法可以分为两类:
第一类: n 份中不包含 1 的分法,为保证每份都 >= 2,可以先拿出 k 个 1 分。到每一份,然后再把剩下的 n- k 分成 k 份即可,分法有: dp[n-k][k]
第二类: n 份中至少有一份为 1 的分法,可以先那出一个 1 作为单独的1份,剩下的 n- 1 再分成 k- 1 份即可,分法有:dp[n-1][k-1]
3.将n划分成若干奇数的划分法:
g[i][j]:将i划分为j个偶数;f[i][j]:将i划分为j个奇数
g[i][j] = f[i - j][j];f[i][j] = f[i - 1][j - 1] + g[i - j][j];
方法可以分为两类:
第一类:i中拿出j个1分到每一份中,将剩余的i-j分成j个奇数
第二类:一份包含奇数1,剩余的i-1分成j-1个奇数;另一种,每份至少大于1,将j个1拿出来分到每一份中,其余i-j分成j份
【noi 2.6_8787】数的划分(DP){附【转】整数划分的解题方法}的更多相关文章
- HDU4632 Poj2955 括号匹配 整数划分 P1880 [NOI1995]石子合并 区间DP总结
题意:给定一个字符串 输出回文子序列的个数 一个字符也算一个回文 很明显的区间dp 就是要往区间小的压缩! #include<bits/stdc++.h> using namesp ...
- CodeForces 768E SG函数 整数划分 Game of Stones
一个标准的NIM游戏 加上一条规则:每堆石子对于每个数目的石子只能被取一次 可以SG打表 dp[i][j]表示现在有i个石子 j是可以取的石子数的状压 第i位为1就表示i个石子没被取过 #includ ...
- NOI.AC 31 MST——整数划分相关的图论(生成树、哈希)
题目:http://noi.ac/problem/31 模拟 kruscal 的建最小生成树的过程,我们应该把树边一条一条加进去:在加下一条之前先把权值在这一条到下一条的之间的那些边都连上.连的时候要 ...
- 51nod 1201 整数划分 基础DP
1201 整数划分 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 收藏 关注 将N分为若干个不同整数的和,有多少种不同的划分方式,例如:n = 6,{6} ...
- NYOJ90 整数划分(经典递归和dp)
整数划分 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 将正整数n表示成一系列正整数之和:n=n1+n2+…+nk, 其中n1≥n2≥…≥nk≥1,k≥1. 正 ...
- HDU 1028 Ignatius and the Princess III dp整数划分
http://acm.hdu.edu.cn/showproblem.php?pid=1028 dp[i][j]表示数值为i,然后最小拆分的那个数是j的时候的总和. 1 = 1 2 = 1 + 1 . ...
- bzoj 3612: [Heoi2014]平衡【整数划分dp】
其实就是-n~n中求选k个不同的数,和为0的方案数 学到了新姿势叫整数划分,具体实现是dp 详见:https://blog.csdn.net/Vmurder/article/details/42551 ...
- 【NOI2019模拟2019.6.27】B (生成函数+整数划分dp|多项式exp)
Description: \(1<=n,k<=1e5,mod~1e9+7\) 题解: 考虑最经典的排列dp,每次插入第\(i\)大的数,那么可以增加的逆序对个数是\(0-i-1\). 不难 ...
- 2014北大研究生推免机试(校内)-复杂的整数划分(DP进阶)
这是一道典型的整数划分题目,适合正在研究动态规划的同学练练手,但是和上一个随笔一样,我是在Coursera中评测通过的,没有找到适合的OJ有这一道题(找到的ACMer拜托告诉一声~),这道题考察得较全 ...
随机推荐
- Linux 入门教程:00 Background
Linux 为何物? 就是一个操作系统. Linux 历史: 操作系统始于二十世纪五十年代,当时的操作系统能运行批处理程序.批处理程序不需要用户的交互,它从文件或者穿孔卡片读取数据,然后输出到另外一个 ...
- XSS类型,防御及常见payload构造总结
什么是XSS? XSS全称是Cross Site Scripting即跨站脚本,当目标网站目标用户浏览器渲染HTML文档的过程中,出现了不被预期的脚本指令并执行时,XSS就发生了. 最直接的例子:&l ...
- C语言补码(C语言学习笔记)
记录 在学习C语言数据范围时了解到了补码的概念,记录一下什么是补码,补码怎么运算的 运算 原文链接:https://www.cnblogs.com/lsgsanxiao/p/5113305.html ...
- 腾讯云COS对象存储占据数据容灾C位
说到公有云容灾,大家首先想到的是云上数据备份. 然而,随着企业核心业务逐渐从线下迁移到云上,客户提出了更高的要求.如何确保云上业务的高可用.数据的高可靠,这对云厂商提出了新的挑战. 腾讯云作为全球领先 ...
- 萌新入门之python基础语法
首先我们先了解一些python最最基础的入门 1.标识符 定义:我们写代码的时候自己取得名字比如项目名,包名,模块名这些: 规范:1.数字/字母/下划线组成,不能以数字开头 2.起名字要见名知意 3. ...
- OLE NumberFormat
设置单元格的数字格式, $3.00 想搞出这样的格式,在VBA里的格式定义如下 $#,##0.00;-$#,##0.00 可是在abap里,就是不行.最后尝试了很多次,原来在在$前面加\变成\$#,# ...
- java 不利用第三个变量的情况下将值互换
package com.zcj.eg001; public class VarChange { public static void main(String[] args) { int a = 10; ...
- 阅读lodash源码之旅数组方法篇-compact和concat
鲁迅说过:只有阅读过优秀库源码的人,才能配的上是真正的勇士. compact 创建一个新数组,包含原数组中所有的非假值元素.例如false, null,0, "", undefin ...
- OpenStack各组件的常用命令
openstack命令 openstack-service restart #重启openstack服务 openstack endpoint-list #查看openstack的 ...
- 【UltraISO】中文破解版
下载链接:https://cn.ultraiso.net/uiso9_cn.exe简体中文版专用: 注册名:Guanjiu 注册码:A06C-83A7-701D-6CFC多国语言版专用: ...