[bzoj 3687] 简单题:bitset,DP
来源:互联网 发布:矩阵理论张绍飞 编辑:程序博客网 时间:2024/06/05 15:01
总有些题的名字比较逗……诸如“简单题”、“绝世好题”等等。
题意:求一个可重数集的子集的算数和的异或和。元素个数n不超过1000个,所有数是正整数,总和不超过2000000。
两次碰到bitset,都没做出来,学习一下。事先知道这道题可以用bitset来做。
bitset是一种STL容器,即位向量,用bitset<N>
来定义,N是位数。可以用string
来初始化,注意string
的最低位是bitset
的最高位。
可以用[]
运算符来访问或修改bitset中的某一位,也可以set
、reset
、flip
,以及用test
来查看某一位(可以扔出一个异常)。测试整个bitset是否为空用none
,测试是否非空用any
,数有多少个1用count
。转换为其他形式有to_string
、to_ulong
。bitset重载了位运算符。
给了两个方面的数据范围。“n<1000”告诉我们枚举子集不靠谱,设计分治算法失败,那么能否从“总和不超过2000000”入手?如果我能知道,对于给定数k,有多少个子集的算数和等于k就好了。DP可以解决,类似于背包。(插入:刚学到用DP求解背包问题是个伪多项式算法。)但还是慢……
把转移方程写出来: f[i][j] = f[i-1][j-a[i]] + f[i-1][j]
每一轮中,j
由原来的与j-a[i]
叠加转移而来。把a[i]
固定,这个动作很有规律,能不能一起做?我想到了矩阵乘法(虽然关联不大,但转移矩阵正是描述这一类动作的),想到了平移,想到了位运算中的左移右移。妙哉!
#include <cstdio>#include <bitset>using namespace std;const int MAX_S = 2000000;bitset<MAX_S+1> f;int main(){ int n, a, ans = 0; scanf("%d", &n); f.set(0); for (int i = 0; i < n; ++i) { scanf("%d", &a); f ^= f << a; } for (int i = 1; i <= MAX_S; ++i) if (f[i]) ans ^= i; printf("%d\n", ans); return 0;}
0 0
- [bzoj 3687] 简单题:bitset,DP
- 【BZOJ 3687】简单题 dp+bitset
- bzoj 3687: 简单题 (dp+bitset)
- 【BZOJ】3687 简单题 DP+bitset
- BZOJ 3687 简单题【dp,bitset基础应用
- bzoj 3687 简单题|bitset
- BZOJ 3687: 简单题 bitset 题解
- [bitset]BZOJ 3687——简单题
- BZOJ 3687 简单题 (bitset)
- bzoj 3687 简单题 bitset 解题报告
- 【BZOJ】【P3687】【简单题】【题解】【bitset】
- [BZOJ2687]简单题(dp+bitset优化)
- bzoj 3687 bitset
- BZOJ-3687 Bitset运用
- BZOJ 3687 bitset 解题报告
- 【bzoj3687】 简单题 bitset
- 【bzoj3687】【简单题】【bitset】
- 【BZOJ3687】简单题【bitset】
- 相对布局控制控件居右显示
- 线性表
- 利用两个栈实现一个队列
- 线性布局控制控件居右显示
- Keras笔记 -- objective
- [bzoj 3687] 简单题:bitset,DP
- BPTT-应用于简单的循环神经网络
- 嗯嗯
- Matlab基础之矩阵循环
- 七层网络协议
- TCP/IP协议
- [160826]Steins Gate 0(命运石之门0)【日文硬盘版】[带全CG存档&攻略+修正&打开存档补丁]
- 有关Linux(6)
- java synchronized详解