【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拜托告诉一声~),这道题考察得较全 ...
随机推荐
- 【SpringBoot1.x】SpringBoot1.x 消息
SpringBoot1.x 消息 文章源码 概述 大多应用中,可通过消息服务中间件来提升系统异步通信.扩展解耦能力. 消息服务有两个重要概念,即消息代理(message broker)和目的地(des ...
- GCC 概述:C 语言编译过程详解
Tags: C Description: 关于 GCC 的个人笔记 GCC 概述 对于 GCC 6.1 以及之后的版本,默认使用的 C++ 标准是 C++ 14:使用 -std=c++11 来指定使用 ...
- 【Spring】XML方式实现(无参构造 有参构造)和注解方式实现 IoC
文章目录 Spring IoC的实现方式 XML方式实现 通过无参构造方法来创建 1.编写一个User实体类 2.编写我们的spring文件 3.测试类 UserTest.java 4.测试结果 通过 ...
- 【Software Test】Basic Of ST
文章目录 Learning Objective Introduction Software Applications Before Software Testing What is testing? ...
- kubernets之secret资源
一 对于一些保密度比较高的文件,k8s又是如何存储的呢? 针对那些保密度比较高的配置文件,例如证书以及一些认证配置不能直接存储在configmap中,而是需要存储在另外一种资源中,需要对存储在里面的 ...
- 07--Docker安装Redis
1.拉取redis:3.2 docker pull redis:3.2 2.创建redis容器 docker run -p 6379:6379 -v /zhengcj/myredis/data:/da ...
- 02--Docker配置阿里云镜像加速器
1.登录阿里云控制台,在产品与服务中收索 "容器镜像服务" 2.点击镜像加速器,CentOS 3.在路径 /etc/docker/daemon.json 下配置加速器地址 4.重新 ...
- 2.4V升3.3V,2.4V升3V,1A大电流升压芯片
两节镍氢电池串联就是1.2V+1.2V=2.4V的供电电压了,2.4V升3V, 2.4V升3.3V的话,就能稳压稳定给模块供电了,镍氢电池是会随着使用的电池电量减少的话,电池的电压也是跟着变化的,导致 ...
- three.js cannon.js物理引擎之Heightfield
今天郭先生说一说cannon.js物理引擎之Heightfield高度场,学过场论的朋友都知道物理学中把某个物理量在空间的一个区域内的分布称为场,高度场就是与高度相关的场,而cannon.js物理引擎 ...
- Android N selectQualifiedNetwork分析
前言: 参考:Android N wifi auto connect流程分析 后续 Android 8.0/9.0 wifi 自动连接评分机制 分析 前面说了,handleScanResults会去调 ...