Codeforces 1188D - Make Equal(dp)
首先我们考虑枚举最后这 \(n\) 个数变成的值 \(v\),那么需要的操作次数即为 \(\sum\limits_{i=1}^n\text{bitcnt}(v-a_i)\),其中 \(\text{bitcnt}(x)\) 为 \(x\) 二进制中 \(1\) 的个数。
这样似乎不太好直接求,不过不难发现这个 \(v\) 一定是 \(\ge\max\{a_i\}\) 的,因此我们考虑转而枚举 \(x=v-\max\{a_i\}\),我们记 \(b_i=\max\{a_j\}-a_i\),那么操作次数又可写为 \(\sum\limits_{i=1}\text{bitcnt}(b_i+x)\)。
显然最优方案下的 \(x\) 必然 \(< 2^{60}\),否则我们总可以找到某一位 \(y\ge 60\) 满足 \(x\) 的 \(2^y\) 为 \(1\),此时考虑令 \(x\leftarrow x-2^y\),答案不会变得更劣。因此我们考虑按位决策,即先考虑 \(x\) 二进制下的最低位,再考虑二进制下的次低位,以此类推。对于 \(x\) 的每一位 \(2^p\),它对答案产生的影响显然就是满足 \(a_i+x\) 的 \(2^p\) 位为 \(1\) 的 \(i\) 的个数,考虑这个个数的影响因素,显然这东西会受到以下三点的影响:
- 每个 \(a_i\) 的 \(2^p\) 位上的值
- \(x\) 的 \(2^p\) 位上的值
- \(a_i+x\) 在 \(2^{p-1}\) 位是否产生了进位
第一点显然开个桶记录一下就行了,第二点就直接枚举 \(x\) 的 \(2^p\) 位是 \(0\) 还是 \(1\) 并分别计算一下即可。棘手的地方在于第三点,共 \(2^n\) 个状态,如果简简单单将其放入 \(dp\) 状态中那连暴力都跑不过,完全不能接受。
不过注意到我们所加的数 \(x\) 是相同的。稍微想想就能知道,\(a_i\bmod 2^p\) 越大的肯定越容易产生进位。因此倘如我们将所有 \(a_i\) 按 \(a_i\bmod 2^p\) 从小到大排序,产生进位的 \(a_i\) 必定是一段后缀。也就是说只要知道有多少个 \(a_i+x\) 在 \(2^{p-1}\) 位产生了进位,就能知道是哪些 \(a_i\) 产生了进位。因此我们设 \(dp_{i,j}\) 表示考虑了前 \(i\) 位,当前位有 \(j\) 个产生进位的最小 \(1\) 的个数,考虑转移,我们假设已经确定了 \(x\) 的前 \(i\) 位,有 \(j\) 个数产生进位,那么按照 \(a_t+x\) 是否在 \(2^i\) 位产生进位,以及 \(a_t\) 的 \(2^{i+1}\) 位的取值可分为 \(4\) 类:
- \(a_t+x\) 在 \(2^i\) 位产生了进位且 \(a_t\) 的 \(2^{i+1}\) 位为 \(1\)
- \(a_t+x\) 在 \(2^i\) 位产生了进位且 \(a_t\) 的 \(2^{i+1}\) 位为 \(0\)
- \(a_t+x\) 在 \(2^i\) 位没有产生进位且 \(a_t\) 的 \(2^{i+1}\) 位为 \(1\)
- \(a_t+x\) 在 \(2^i\) 位没有产生进位且 \(a_t\) 的 \(2^{i+1}\) 位为 \(0\)
我们枚举 \(x\) 的 \(2^{i+1}\) 位是什么,那么
- \(x\) 的 \(2^{i+1}\) 位为 \(0\),那么第一类数会产生进位,第二、三类数 \(2^{i+1}\) 位为 \(1\),贡献随便算
- \(x\) 的 \(2^{i+1}\) 位为 \(1\),那么第一、二、三类数会产生进位,第一、四类数 \(2^{i+1}\) 位为 \(1\)。
时间复杂度 \(n\log^2n\)。
const int MAXB=60;
const int MAXN=1e5;
int n,ord[MAXN+5];ll a[MAXN+5],b[MAXN+5];
int dp[MAXB+5][MAXN+5],sum[MAXN+5][2];
int main(){
scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
sort(a+1,a+n+1);for(int i=1;i<=n;i++) a[i]=a[n]-a[i];
memset(dp,63,sizeof(dp));dp[0][0]=0;
for(int i=0;i<=MAXB;i++){
memset(sum,0,sizeof(sum));
for(int j=1;j<=n;j++) b[j]=a[j]&((1ll<<i)-1);
for(int j=1;j<=n;j++) ord[j]=j;
sort(ord+1,ord+n+1,[](int x,int y){return b[x]<b[y];});
for(int j=1;j<=n;j++){
sum[j][0]=sum[j-1][0];sum[j][1]=sum[j-1][1];
sum[j][a[ord[j]]>>i&1]++;
}
for(int j=0;j<=n;j++){
int cst=sum[n-j][1]+sum[n][0]-sum[n-j][0],carry=sum[n][1]-sum[n-j][1];
chkmin(dp[i+1][carry],dp[i][j]+cst);
cst=sum[n-j][0]+sum[n][1]-sum[n-j][1],carry=n-sum[n-j][0];
chkmin(dp[i+1][carry],dp[i][j]+cst);
}
} printf("%d\n",dp[MAXB+1][0]);
return 0;
}
Codeforces 1188D - Make Equal(dp)的更多相关文章
- Codeforces Gym101341K:Competitions(DP)
http://codeforces.com/gym/101341/problem/K 题意:给出n个区间,每个区间有一个l, r, w,代表区间左端点右端点和区间的权值,现在可以选取一些区间,要求选择 ...
- codeforces 711C Coloring Trees(DP)
题目链接:http://codeforces.com/problemset/problem/711/C O(n^4)的复杂度,以为会超时的 思路:dp[i][j][k]表示第i棵数用颜色k涂完后bea ...
- codeforces#1154F. Shovels Shop (dp)
题目链接: http://codeforces.com/contest/1154/problem/F 题意: 有$n$个物品,$m$条优惠 每个优惠的格式是,买$x_i$个物品,最便宜的$y_i$个物 ...
- Codeforces 1051 D.Bicolorings(DP)
Codeforces 1051 D.Bicolorings 题意:一个2×n的方格纸,用黑白给格子涂色,要求分出k个连通块,求方案数. 思路:用0,1表示黑白,则第i列可以涂00,01,10,11,( ...
- Codeforces 1207C Gas Pipeline (dp)
题目链接:http://codeforces.com/problemset/problem/1207/C 题目大意是给一条道路修管道,相隔一个单位的管道有两个柱子支撑,管道柱子高度可以是1可以是2,道 ...
- Codeforces 704C - Black Widow(dp)
Codeforces 题目传送门 & 洛谷题目传送门 u1s1 感觉这种题被评到 *2900 是因为细节太繁琐了,而不是题目本身的难度,所以我切掉这种题根本不能说明什么-- 首先题目中有一个非 ...
- Codeforces 682B New Skateboard(DP)
题目大概说给一个数字组成的字符串问有几个子串其代表的数字(可以有前导0)能被4整除. dp[i][m]表示字符串0...i中mod 4为m的后缀的个数 通过在i-1添加str[i]字符转移,或者以st ...
- Codeforces 543D Road Improvement(DP)
题目链接 Solution 比较明显的树形DP模型. 首先可以先用一次DFS求出以1为根时,sum[i](以i为子树的根时,满足要求的子树的个数). 考虑将根从i变换到它的儿子j时,sum[i]产生的 ...
- Codeforces 543C Remembering Strings(DP)
题意比较麻烦 见题目链接 Solution: 非常值得注意的一点是题目给出的范围只有20,而众所周知字母表里有26个字母.于是显然对一个字母进行变换后是不影响到其它字符串的. 20的范围恰好又是常见状 ...
随机推荐
- Linux主机入侵检测
检查系统信息.用户账号信息 ● 操作系统信息 cat /proc/version 用户信息 用户信息文件 /etc/passwd root:x:0:0:root:/root:/bin/bash 用户名 ...
- Java:异常小记
Java:异常小记 对 Java 中的 异常 ,做一个微不足道的小小小小记 Error 和 Exception 相同点: Exception 和Error 都是继承了 Throwable 类,在 Ja ...
- [no code][scrum meeting] Alpha 13
项目 内容 会议时间 2020-04-21 会议主题 OCR技术对接会议 会议时长 45min 参会人员 全体成员 $( "#cnblogs_post_body" ).catalo ...
- OO前三次作业思考(第一次OO——Blog)
OO前三次作业总结 基于度量分析程序结构 由于三次作业较多,决定分析内容.功能最为复杂的第三次作业. 上图为第三次作业的类图.我使用了一个抽象类Factor,写了五个因子继承Factor,然后又单独开 ...
- 使用spire.doc导出支持编辑Latex公式的标准格式word
背景 之前有的教辅标注需求,在导出题库的时候希望顺便导出可以查看word,方便线下预览成品效果,因为只是用来预览并且为了沿用前端的样式,当时方案就是直接生成html,写个word的文件头,这样就可以用 ...
- 深入了解Mybatis架构设计
架构设计 我们可以把Mybatis的功能架构分为三层: API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库.接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理. ...
- 精心整理Java微服务最全面试题集(含答案)
微服务架构相关 大型网站架构演变过程 网站架构演变演变过程 传统架构 → 分布式架构 → SOA架构 → 微服务架构 什么是分布式架构 分布式架构就是将传统结构按照模块进行拆分,不同的人负责不同的模块 ...
- 网关服务spring cloud zuul
Zuul例子配置文件 spring.application.name=switch-gateway server.port=5555 请求路由 传统路由方式 zuul.routes.api-a-url ...
- docker使用redis过程出现的问题记录
第一次使用docker搭建成功了单机版redis,但在使用过程中,还是遇到了不少问题,故而先把这些问题记录下来,以防后面再出现会忘记. 目前,只是在docker中搭建了三个单机版的容器,打算先捣鼓一周 ...
- linux运维思想
1.安装部署某个服务或者研究某个知识点时,宁可花大量时间,也需要尽量将该服务搞透,后续再遇到相关问题时你会发现这为你节省的时间将远远比你当时花的时间多. 2.安装部署时,做好记录,发本地记录并发表博文 ...