分组选数

题目大意:

给 \(n\) 个数,第 \(i\) 个数是 \(a_i\),属于第 \(b_i\) 个集合中。对于每个集合,若从中选出若干个数,则价值为这些数的异或和,总共的价值就是所有集合的价值的和。现在最多可以选 \(m\) 个数,问可以获得的最大价值是多少。

数据范围:

对于 \(100\%\) 的数据:

  • \(n, m \leq 2000\)
  • \(a_i \leq 2000\)
  • \(b_i \leq 2000\)

解题分析:

朴素做法:

假设 \(a_{i,j}\) 为第 \(i\) 个集合中的第 \(j\) 个数。

首先,最质朴的想法就是设 \(f_{i,j,k,l}\) 为第 \(i\) 个集合里,前 \(j\) 个数中选择 \(k\) 个数能否凑成 \(l\)。由于异或运算符是可逆的,所以转移方程就是:

\[f_{i,j,k,l} = f_{i,j-1,k,l} | f_{i,j-1,k-1,l \ \texttt{xor} \ a_{i,j}}
\]

然后再进行一个背包,这里 \(g_{i,j}\) 为前 \(i\) 个集合中选 \(j\) 个数的最大答案:

\[g_{i,j}=\max(g_{i,j}, g_{i - 1,j - k} + \text{第 i 个集合里选 k 个数的答案})
\]

PS:这里 \(k\) 是任意一个数

正解:

但很明显,朴素做法时间复杂度是 \(O(n^3)\),会超时,所以我们不妨观察一下状态。由于异或并不满足最优子结构,所以我们把目光转移到了这个:选择 k 个数

在尝试将状态变成 f[i][j][l] 表示第 i 个集合中,前 j 个数异或和为 l 最少要选择多少个数 后,我们发现这是可以计算的:

\[f_{i,j,l}=\min(f_{i,j-1,l \ \texttt{xor} \ a_{i,j}}, f_{i,j-1,l})
\]

然后对于第 \(i\) 个集合中选择 \(k\) 个数的异或和,我们不妨把它设为 \(c_{i,k}\),然后很明显:

\[c_{i,f_{\text{第 i 个集合的大小}, j}} = \max(c_{i,f_{\text{第 i 个集合的大小}, j}}, j)
\]

注意:由于答案一定是最优的,所以只更新 最少要取多少个数 是没有问题的,因为大一点的更新后要用的数量更多反而会不好。

然后 \(g\) 的更新还是没有区别:

\[g_{i,j}=\max(g_{i,j}, g_{i-1,j-k}+c_{i,k})
\]

然后这道题就做完了,时间复杂度 \(O(n^2)\) (大概吧,反正是这个量级的)

AC Code:

# include <bits/stdc++.h>
using namespace std; # define ll long long
# define lf double
# define int ll
# define GO(i,a,b) for(int i = a; i <= b; i ++)
# define RO(i,b,a) for(int i = b; i >= a; i --)
# define FO(i,u,head,e) for(int i = head[u]; i; i = e[i].next)
# define CI const int
# define pii pair<int,int>
# define F first
# define S second
# define PB(x) push_back(x)
# define mem(a,x) memset(a, x, sizeof a) CI maxn = 2007; int n, m;
map <int, vector <int> > p;
int x, y;
int f[3007][3007]; // 一个集合中前 i 个元素异或和为 j 所用的最少个数
int s[3007]; // 用 i 个数最大的异或和
int g[3007][3007]; // 前 i 个集合选 j 个数最大和 signed main(){
cin >> n >> m;
GO (i, 1, n){
scanf("%lld %lld", &x, &y);
p[y].PB(x);
}
GO (i, 0, 3000)
GO (j, 0, 3000)
g[i][j] = -2e18;
g[0][0] = 0;
int ii = 0;
int ans = -2e18;
for (auto i : p){
ii ++;
auto x = (i.S);
GO (j, 0, (int) (x.size()))
GO (k, 0, 3000)
f[j][k] = 2e18, s[k] = 0;
f[0][0] = 0;
GO (j, 1, (int) (x.size()))
GO (k, 0, 2000)
f[j][k] = min <int> (f[j - 1][k ^ x[j - 1]] + 1, f[j - 1][k]);
GO (k, 0, 2000) if (f[(int)(x.size())][k] != 2e18) s[f[(int)(x.size())][k]] = max <int> (s[f[(int)(x.size())][k]], k);
GO (j, 0, 2000)
GO (k, 0, min <int> (j, (int) (x.size())))
g[ii][j] = max <int> (g[ii][j], g[ii - 1][j - k] + s[k]);
}
GO (j, 0, m) ans = max <int> (ans, g[ii][j]);
printf("%lld", ans);
return 0;
}

[J组模拟赛 #002 T4]分组选数的更多相关文章

  1. SX【2020.01.09】NOIP提高组模拟赛(day1)

    [2020.01.09]NOIP提高组模拟赛(day1) 这次考得不理想,只做了前两题,后两题没时间做,说明做题速度偏慢. source : 100 + 20 + 0 + 0 = 120 rank7 ...

  2. 52-2018 蓝桥杯省赛 B 组模拟赛(一)java

    最近蒜头君喜欢上了U型数字,所谓U型数字,就是这个数字的每一位先严格单调递减,后严格单调递增.比如 212212 就是一个U型数字,但是 333333, 9898, 567567, 313133131 ...

  3. NOIP2017提高组模拟赛 10 (总结)

    NOIP2017提高组模拟赛 10 (总结) 第一题 机密信息 FJ有个很奇怪的习惯,他把他所有的机密信息都存放在一个叫机密盘的磁盘分区里,然而这个机密盘中却没有一个文件,那他是怎么存放信息呢?聪明的 ...

  4. 2017.1.16【初中部 】普及组模拟赛C组总结

    2017.1.16[初中部 ]普及组模拟赛C组 这次总结我赶时间,不写这么详细了. 话说这次比赛,我虽然翻了个大车,但一天之内AK,我感到很高兴 比赛 0+15+0+100=115 改题 AK 一.c ...

  5. ZROI提高组模拟赛05总结

    ZROI提高组模拟赛05总结 感觉是目前为止最简单的模拟赛了吧 但是依旧不尽人意... T1 有一半的人在30min前就A掉了 而我花了1h11min 就是一个简单的背包,我硬是转化了模型想了好久,生 ...

  6. ZROI 普及组模拟赛02总结

    ZROI 普及组模拟赛02总结 先放[网址][http://zhengruioi.com/contest/96] 可能是有一段时间没有打这种正式的比赛了,今天打的很奇怪... T1 模拟水题 既然是普 ...

  7. NOIP2017提高组 模拟赛15(总结)

    NOIP2017提高组 模拟赛15(总结) 第一题 讨厌整除的小明 [题目描述] 小明作为一个数学迷,总会出于数字的一些性质喜欢上某个数字,然而当他喜欢数字k的时候,却十分讨厌那些能够整除k而比k小的 ...

  8. NOIP2017提高组 模拟赛13(总结)

    NOIP2017提高组 模拟赛13(总结) 第一题 函数 [题目描述] [输入格式] 三个整数. 1≤t<10^9+7,2≤l≤r≤5*10^6 [输出格式] 一个整数. [输出样例] 2 2 ...

  9. NOIP2017提高组模拟赛 8(总结)

    NOIP2017提高组模拟赛 8(总结) 第一题 路径 在二维坐标平面里有N个整数点,Bessie要访问这N个点.刚开始Bessie在点(0,0)处. 每一步,Bessie可以走到上.下.左.右四个点 ...

  10. NOIP2017提高组模拟赛 9 (总结)

    NOIP2017提高组模拟赛 9 (总结) 第一题 星星 天空中有N(1≤N≤400)颗星,每颗星有一个唯一的坐标(x,y),(1≤x,y ≤N).请计算可以覆盖至少K(1≤K≤N)颗星的矩形的最小面 ...

随机推荐

  1. Flutter视频压缩技术:如何在应用中优化视频文件的质量和大小?

    @charset "UTF-8"; .markdown-body { line-height: 1.75; font-weight: 400; font-size: 15px; o ...

  2. .NET 10 Preview 4中ASP.NET Core 改进

    .NET团队在5月13日发布了.NET 10 Preview 4: https://devblogs.microsoft.com/dotnet/dotnet-10-preview-4/.该版本虽无突破 ...

  3. codeup之输出梯形

    Description 输入一个高度h,输出一个高为h,上底边为h的梯形. Input 一个整数h(1<=h<=1000). Output h所对应的梯形. Sample Input Co ...

  4. 如何下载DingTalk的直播视频?

    如何下载DingTalk的直播视频? 说明:本文未经授权禁止转载 绪言 如果有天早上 你突发奇想 突然就想把老师上课的视频下载下来 但是 正在寻找下载按钮时 突然发现-- 灰色的?!?! 看来是老师禁 ...

  5. 分布式可视化 DAG 任务调度系统 Taier 的整体流程分析

    Taier 作为袋鼠云的开源项目之一,是一个分布式可视化的 DAG 任务调度系统.旨在降低 ETL 开发成本,提高大数据平台稳定性,让大数据开发人员可以在 Taier 直接进行业务逻辑的开发,而不用关 ...

  6. Web前端入门第 70 问:JavaScript DOM 节点查找常用方法

    虽然目前的开发场景基本都是使用 React/Vue/Angular 等框架,但是对于一些基础的 DOM 操作,还是需要了解学习. 曾经我们讨论过这样一个问题:Vue 这些开发框架,用它们渲染页面,真的 ...

  7. 分布式事务-2PC

    目录 1. 2PC是什么 2. 2PC流程 3. 2PC的使用场景 4. 2PC的问题 5. 2PC的实现 5.1. XA 5.2. Seata的XA模式 6. 参考 1. 2PC是什么 保证强一致性 ...

  8. 4G CAT1 DTU RS232/485转4G Modbus RTU转4G Modbus TCP RS232/485转MQTT DLT-645/RTU转云平台JSON

    4G CAT1 DTU   RS232/485转4G   Modbus RTU转4G Modbus TCP   RS232/485转MQTT   DLT-645/RTU转云平台JSON 高性价比的CA ...

  9. GPRS DTU

    GPRS DTU ZLAN8305/ZLAN8305L是上海卓岚新推出的一款高性价比的串口232/485转GPRS DTU.这款的核心亮点是支持M级别的数据暂时存储 高性价比 支持MQTT 支持全网通 ...

  10. 4G DTU连接阿里云

    随着物联网平台的应用越来越广泛,越来越多的用户需求数据通过4G DTU传到阿里云,然后用户从阿里云上实时获取需要的数据,本文介绍卓岚设备ZLAN8305/ZLAN5144J如何通过MQTT功能和JSO ...