soj 2785 Binary Partitions (构造类似完全背包)
2015-10-23 07:50
253 查看
@(K ACMer)
题意:
给你一个数n,求它的二进制表达有多少种?
(注意两个二进制表达的元素是相同的,则认为他们是相同的,与顺序无关)
我们假设n等于5,来观察一下暴力的解法.
首先5个1肯定是最简单地表达方式:1+1+1+1+1它的种数显然为1.
然后最右边的两个1可以合并为2,即:1+1+1+2
然后:1+2+2
然后:1+4
这样我们可以构造一个类似完全背包的解法出来,选取物品顺序j为20,21,22....2i(2i<=maxn)
定义dp[i]为当前i的i2进制表达的总数,有转移方程:dp[i]+=dp[i−j]这样每次选择一个j的时候dp[i-j] 已经包含了它有j的种数,我们只需要在最后加一个j就是了.(如果这句话较难理解,可以直接模拟一遍5的dp过程加以理解).
这里的dp其实体现在每次增加一个二进制数的时候,可以由小的数到大的数来加,并且小的数的结果可以直接被大的数利用,这里是一种记忆的思想,而这个二进制数可以想选最多个,也是一中完全背包的思想.
题意:
给你一个数n,求它的二进制表达有多少种?
(注意两个二进制表达的元素是相同的,则认为他们是相同的,与顺序无关)
我们假设n等于5,来观察一下暴力的解法.
首先5个1肯定是最简单地表达方式:1+1+1+1+1它的种数显然为1.
然后最右边的两个1可以合并为2,即:1+1+1+2
然后:1+2+2
然后:1+4
这样我们可以构造一个类似完全背包的解法出来,选取物品顺序j为20,21,22....2i(2i<=maxn)
定义dp[i]为当前i的i2进制表达的总数,有转移方程:dp[i]+=dp[i−j]这样每次选择一个j的时候dp[i-j] 已经包含了它有j的种数,我们只需要在最后加一个j就是了.(如果这句话较难理解,可以直接模拟一遍5的dp过程加以理解).
这里的dp其实体现在每次增加一个二进制数的时候,可以由小的数到大的数来加,并且小的数的结果可以直接被大的数利用,这里是一种记忆的思想,而这个二进制数可以想选最多个,也是一中完全背包的思想.
#include <cstdio> #include <cstring> using namespace std; const int maxn = (1e6 + 9) * 2, INF = 0x3fffffff, mod = 1e6; typedef long long ll; int dp[maxn]; int a[maxn]; #define max(x, y) (x) > (y) ? (x) : (y) int main(void) { int n, maxs = -INF; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); maxs = max(a[i], maxs); } dp[0] = 1; for (int i = 1; i <= maxs; i <<= 1) { for (int j = i; j <= maxs; j++) { dp[j] += dp[j - i] % mod; } } for (int i = 0; i < n; i++) { printf("%d\n", dp[a[i]] % mod); } return 0; }
相关文章推荐
- AsyncTask的使用
- C++异常处理
- linux硬件级虚拟机系统 电脑安桌游戏多开完全去除vm标识去虚拟化
- Leetcode NO.252 Meeting Rooms
- Search in Rotated Sorted Array II
- 151022总结
- 反射
- LeetCode Word Pattern
- 黑马程序员-OC回顾-对象特性
- 由欲从编程菜鸟突破到中级选手遇到的瓶颈想到的
- C#如何实现单例启动和关闭全部窗体
- 网络编程
- 全新 GNOME Games:一款应用驾驭所有游戏
- 黑马程序员-构造函数以及构造函数的重写
- Permutations II
- Permutations
- vim配置文件解析
- 【软考5】解释型 or 编译型
- 【软考5】解释型 or 编译型
- Count in String and Object