POJ 2229 sumset ( 完全背包 || 规律递推DP )
题意 : 给出一个数 n ,问如果使用 2 的幂的和来组成这个数 n 有多少种不同的方案?
分析 :
完全背包解法
将问题抽象==>有重量分别为 2^0、2^1、2^2…2^k 的物品且每种物品可无限取,问有多少种方案来填满容量为 n 的背包?
之前并不知道背包还能用来计数.......
有一道裸的背包计数问题可以作为练习 ==> HDU 1284
定义 dp[ i ][ j ] 为前 i 种物品组成总重量 j 的方案数为多少、初始化为 dp[ 0 ][ 0 ] = 1 其他为 0
则状态转移方程为 dp[ i ][ j ] += dp[ i-1 ][ j - k*w[ i ] ] ( k ≥ 0 && j ≥ k*w[i] )
最后类似于完全背包的递推方程,可化简为一维线性的递推式 dp[ j ] += dp[ j - w[ i ] ] ( j ≥ w[i] )
#include<bits/stdc++.h>
using namespace std;
;
const int mod = 1e9;
int dp[maxn];
int main(void)
{
int n;
while(~scanf("%d", &n)){
memset(dp, , sizeof(dp));
dp[] = ;
; i<; i++)
<<i); j<=n; j++){
dp[j] += dp[j-(<<i)];
if(dp[j] >= mod) dp[j] -= mod;
}
printf("%d\n", dp[n]);
}
;
}
找递推规律解法
现分别来考虑 n 为奇数还有偶数的情况
① n 为奇数的时候可以发现只是在 n-1( 偶数 ) 每种方案的后面多了个 1 而已并不能多组出新的方案,所以 dp[ 奇数 ] = dp[ 奇数 -1 ]
② n 为偶数,此时可以将所有的方案数分成两类 ( 组合方案中包含 1 的 ) 与 ( 组合方案中不包含 1 的 )
首先来看组合方案中包含 1 的情况
可以将其看成在 n-1 的方案中每个方案的后面多加一个 1 来组成,此时方案数和 n-1 是一样的即 dp[ n - 1 ]
而组合方案中不包含 1 的情况
如果将小数据打表列出来会发现这种情况的方案数实际等于 n/2 的方案数,即 dp[ n/2 ]
所以最后的答案应该为 dp[ n ] = dp[ n-1 ] + dp[ n/2 ]
#include<bits/stdc++.h>
using namespace std;
;
const int mod = 1e9;
int dp[maxn];
int main(void)
{
int n;
while(~scanf("%d", &n)){
dp[] = ;
dp[] = dp[] = ;
dp[] = dp[] = ;
dp[] = dp[] = ;
) printf("%d\n", dp[n]);
else{
; i<=n; i++){
) dp[i] = dp[i-];
] + dp[i>>];
if(dp[i] >= mod) dp[i] -= mod;
}
printf("%d\n", dp[n]);
}
}
;
}
现举几个例子来解释一下
dp[1] = 1
1
------------------------------------------------------------------------------------
dp[2] = 2
1+1、2
------------------------------------------------------------------------------------
dp[3] = dp[3-1] = 2
1+1+1、2+1 ( 奇数情况 == 奇数-1中所有方案数后面添 1 )
------------------------------------------------------------------------------------
dp[4] = dp[4-1] + dp[4/2] = 4
1+1+1+1、2+1+1 ( 这个就是 dp[4-1] 的情况 == 在 n-1 的所有方案数后面添 1 )
2+2、4 ( 这里的所有方案 / 2 后会发现实际就对应了 dp[2] ,所以是 dp[ 4/2 ] )
------------------------------------------------------------------------------------
dp[5] = dp[5-1] = 4
1+1+1+1+1、2+1+1+1
2+2+1、4+1
------------------------------------------------------------------------------------
dp[6] = dp[6-1] + dp[ 6/2 ] = 6
1+1+1+1+1+1、2+1+1+1+1、2+2+1+1、4+1+1 ( 此为 dp[ 6-1 ] 意义和上面所述一样 )
2+2+2、4+2 ( 方案所有数 / 2 后变成 1+1+1、2+1 和 dp[3] 是对应的! )
......
POJ 2229 sumset ( 完全背包 || 规律递推DP )的更多相关文章
- poj 2229 【完全背包dp】【递推dp】
poj 2229 Sumsets Time Limit: 2000MS Memory Limit: 200000K Total Submissions: 21281 Accepted: 828 ...
- ACM_递推题目系列之一涂色问题(递推dp)
递推题目系列之一涂色问题 Time Limit: 2000/1000ms (Java/Others) Problem Description: 有排成一行的n个方格,用红(Red).粉(Pink).绿 ...
- 递推DP URAL 1167 Bicolored Horses
题目传送门 题意:k个马棚,n条马,黑马1, 白马0,每个马棚unhappy指数:黑马数*白马数,问最小的unhappy值是多少分析:dp[i][j] 表示第i个马棚放j只马的最小unhappy值,状 ...
- 递推DP URAL 1017 Staircases
题目传送门 /* 题意:给n块砖头,问能组成多少个楼梯,楼梯至少两层,且每层至少一块砖头,层与层之间数目不能相等! 递推DP:dp[i][j] 表示总共i块砖头,最后一列的砖头数是j块的方案数 状态转 ...
- 递推DP URAL 1260 Nudnik Photographer
题目传送门 /* 递推DP: dp[i] 表示放i的方案数,最后累加前n-2的数字的方案数 */ #include <cstdio> #include <algorithm> ...
- 递推DP URAL 1353 Milliard Vasya's Function
题目传送门 /* 题意:1~1e9的数字里,各个位数数字相加和为s的个数 递推DP:dp[i][j] 表示i位数字,当前数字和为j的个数 状态转移方程:dp[i][j] += dp[i-1][j-k] ...
- 递推DP URAL 1119 Metro
题目传送门 /* 题意:已知起点(1,1),终点(n,m):从一个点水平或垂直走到相邻的点距离+1,还有k个抄近道的对角线+sqrt (2.0): 递推DP:仿照JayYe,处理的很巧妙,学习:) 好 ...
- 递推DP 赛码 1005 Game
题目传送门 /* 递推DP:官方题解 令Fi,j代表剩下i个人时,若BrotherK的位置是1,那么位置为j的人是否可能获胜 转移的时候可以枚举当前轮指定的数是什么,那么就可以计算出当前位置j的人在剩 ...
- 递推DP HDOJ 5328 Problem Killer
题目传送门 /* 递推DP: 如果a, b, c是等差数列,且b, c, d是等差数列,那么a, b, c, d是等差数列,等比数列同理 判断ai-2, ai-1, ai是否是等差(比)数列,能在O( ...
随机推荐
- kms自动激活Windows和Office
采用脚本激活 无毒无公害 下载后解压,然后双击运行即可自动激活 激活脚本点此下载
- python每日一练:0015题
第 0015 题: 纯文本文件 city.txt为城市信息, 里面的内容(包括花括号)如下所示: { "1" : "上海", "2" : & ...
- ARP协议基础
ARP 什么是ARP协议 ARP协议是能够根据IP地址解析出该IP地址所在设备的MAC地址,叫(Address Resolution Protocol)地址解析协议 ARP地址的工作流程 当一台主机A ...
- Redis为什么不能使用一主一从哨兵
哨兵机制 识别挂掉的主节点 quorum(法定人数) 是判定主节点不能访问所需要的最少哨兵数量 执行失效备援perform a failover 其中一个哨兵需要被选为救援的领导,并被授权执行救援,而 ...
- python学习之路 目录
python Python基础-1 python由来 字符编码 注释 pyc文件 python变量 导入模块 获取用户输入 流程控制if while python基础-2 编码转换 pycharm 配 ...
- adb常用命令和抓取log的方法
一 adb常用的几个命令1. 查看设备adb devices这个命令是查看当前连接的设备, 连接到计算机的android设备或者模拟器将会列出显示 C:\Documents and Settings\ ...
- es6 js数组常用方法
一:会改变自身的方法 1.array.push(element1, ...elementN) 添加一个或多个元素到数组的末尾,并返回数组新的长度 2.array.unshift(element1, . ...
- 【Luogu P2201】【JZOJ 3922】数列编辑器
题面: Description 小Z是一个爱好数学的小学生.最近,他在研究一些关于整数数列的性质. 为了方便他的研究,小Z希望实现一个叫做"Open Continuous Lines Pro ...
- Tarjan水题系列(3):HNOI2006 潘多拉的魔盒
题目: 链接 大意: 盒子与盒子之间的关系构成一个有向图 求图上包含节点数最多的路径的节点数 思路: 有向图上求包含节点数最多的路径的节点数 可直接使用tarjan缩点后拓扑dp求得 在此不赘述 此题 ...
- Javascript的是三种字符串连接方式
第一种:用连接符“+”连接字符串 str="a"; str+="b"; 这种方法相对以下两种,最便捷快速.建议100字符以下的连接使用这种连接方式. 第二种:以 ...