博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Avito Code Challenge 2018
阅读量:5109 次
发布时间:2019-06-13

本文共 2958 字,大约阅读时间需要 9 分钟。

注意:sum[ ii ]表示第 ii 块的所有数字和,因为有序,实际上就是一个区间和。

题解:二进制枚举答案ans,怎么枚举呢?从高位到低位放1,如果这个序列划分成m块后,能够sum[1] & sum[2] & ···· & sum[m] = ans,那么这位能够放1。dp[ i ][ j ] 表示 1 ~ i 这i个数能否划成 j 个块,使得 sum[1] & sum[2] & ·····  & sum[j] = ans。dp[ i ][ j ] = 1 only if some p ( j - 1 <= p < i ), dp[ p ][ j - 1 ] = 1 and ( a[ i ] - a[ p ] )&x == x。意思是当存在 1 ~ p 这 p 个数能划分成 j - 1 块,所以当第 j 块的区间和与上 x 等于 x 的时候,这 i  个数能划分成 j 块。怎么判断这些块的与等于ans?显然不能求出所有的区间和然后再进行与操作,转化一下,如果 a & x = x, b & x = x, c & x = x,则 a & b & c = x。正确性我没考证!!!所以这需要单独的判断每个区间就行了。

感受:连着两场的dp都没写出来,dp非常有意思就是有点难理解。

#pragma warning(disable:4996)#include
#include
#include
#include
#include
#define ll long long#define mem(arr, in) memset(arr, in, sizeof(arr))using namespace std;const int maxn = 100;bool dp[maxn][maxn];ll n, m, ans, a[maxn];bool check(ll x) { mem(dp, 0); dp[0][0]=1; for (int i = 1; i <= n; i++) { // 枚举 i 个数 for (int j = 1; j <= i; j++) { // 枚举块,所以写成 j <= min( m, i ) 也行 for (int k = j - 1; k < i; k++) if (dp[k][j - 1] && ((a[i] - a[k]) & x) == x) dp[i][j] = 1; // 一定要从 j - 1 开始 } } return dp[n][m];}int main(){ while (cin >> n >> m) { for (int i = 1; i <= n; i++) cin >> a[i], a[i] += a[i - 1]; ans = 0; for (int i = 60; i >= 0; i--) if (check(ans | 1LL << i)) ans |= 1LL << i; cout << ans << endl; } return 0;}

题解:考虑每个点,包含这个点的区间能够产生不同的数,实际上就是考虑这些区间的子集(2^n-1),先用线段树标记一下,用bitset暴力枚举。

感受:这道题我也没完全搞明白,题解只是一个笑话。重点依然是bitset这个数据结构!!!!其实不是状态转移了,就是bitset优化的暴力而已。对于一个集合,bitset可以枚举出这个集合的任意一个子集的和。注意bitset的每一位代表着什么,然后手动模拟一些数据,体验一下移位和或这两个操作的意思。一定要明白bitset里面的每一位表示什么

#pragma warning(disable:4996)#include
#include
#include
#include
#include
#include
#define ll long long#define lson root<<1#define rson root<<1|1#define mem(arr, in) memset(arr, in, sizeof(arr))using namespace std;const int maxn = 10004;using bs = bitset
;int n, q;vector
v[4 * maxn];void Update(int l, int r, int root, int L, int R, int x) { if (l > R || r < L) return; if (L <= l && r <= R) { v[root].push_back(x); return; } int mid = (l + r) >> 1; Update(l, mid, lson, L, R, x); Update(mid + 1, r, rson, L, R, x);}bs ans;void DFS(int l, int r, int root, bs dp) { bs go = dp; for (auto op : v[root]) go |= go << op; if (l == r) { ans |= go; return; } int mid = (l + r) >> 1; DFS(l, mid, lson, go); DFS(mid + 1, r, rson, go);}int main(){ while (scanf("%d %d", &n, &q) != EOF) { for (int i = 1; i <= q; i++) { int l, r, x; scanf("%d %d %d", &l, &r, &x); Update(1, n, 1, l, r, x); } bs dp; dp[0] = 1; DFS(1, n, 1, dp); int cnt = 0; for (int i = 1; i <= n; i++) if (ans[i]) cnt++; printf("%d\n", cnt); for (int i = 1; i <= n; i++) if (ans[i]) { printf("%d ", i); } printf("\n"); } return 0;}

 

转载于:https://www.cnblogs.com/zgglj-com/p/9112063.html

你可能感兴趣的文章
qt 学习记录5
查看>>
css3常用动画+动画库
查看>>
Form保存顺序
查看>>
unity2d之速度和加速度模拟
查看>>
unity3d之从3ds max导入素材到unity中的设置
查看>>
操作系统知识总结
查看>>
springboot多环境下maven打包
查看>>
【转】[钉钉通知系列]Jenkins发布后自动通知
查看>>
欧拉函数模板
查看>>
为什么 jmeter 分布式测试,一定要设置 java.rmi.server.hostname
查看>>
爱牛网站
查看>>
Windows系统SNMP数据监测与OID
查看>>
在CMD命令行下关闭进程的命令
查看>>
resin
查看>>
flow类型检查
查看>>
「Luogu P3183」[HAOI2016]食物链 解题报告
查看>>
腾讯云Ubuntu安装JDK和Tomcat
查看>>
JQuery基本知识、选择器、事件、DOM操作、动画
查看>>
java虚拟机(十一)--GC日志分析
查看>>
工作外的八小时,才能决定你究竟会成为一个什么样的人(转)
查看>>