Codeforces 题目传送门 & 洛谷题目传送门

首先我们考虑枚举最后这 \(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)的更多相关文章

  1. Codeforces Gym101341K:Competitions(DP)

    http://codeforces.com/gym/101341/problem/K 题意:给出n个区间,每个区间有一个l, r, w,代表区间左端点右端点和区间的权值,现在可以选取一些区间,要求选择 ...

  2. codeforces 711C Coloring Trees(DP)

    题目链接:http://codeforces.com/problemset/problem/711/C O(n^4)的复杂度,以为会超时的 思路:dp[i][j][k]表示第i棵数用颜色k涂完后bea ...

  3. codeforces#1154F. Shovels Shop (dp)

    题目链接: http://codeforces.com/contest/1154/problem/F 题意: 有$n$个物品,$m$条优惠 每个优惠的格式是,买$x_i$个物品,最便宜的$y_i$个物 ...

  4. Codeforces 1051 D.Bicolorings(DP)

    Codeforces 1051 D.Bicolorings 题意:一个2×n的方格纸,用黑白给格子涂色,要求分出k个连通块,求方案数. 思路:用0,1表示黑白,则第i列可以涂00,01,10,11,( ...

  5. Codeforces 1207C Gas Pipeline (dp)

    题目链接:http://codeforces.com/problemset/problem/1207/C 题目大意是给一条道路修管道,相隔一个单位的管道有两个柱子支撑,管道柱子高度可以是1可以是2,道 ...

  6. Codeforces 704C - Black Widow(dp)

    Codeforces 题目传送门 & 洛谷题目传送门 u1s1 感觉这种题被评到 *2900 是因为细节太繁琐了,而不是题目本身的难度,所以我切掉这种题根本不能说明什么-- 首先题目中有一个非 ...

  7. Codeforces 682B New Skateboard(DP)

    题目大概说给一个数字组成的字符串问有几个子串其代表的数字(可以有前导0)能被4整除. dp[i][m]表示字符串0...i中mod 4为m的后缀的个数 通过在i-1添加str[i]字符转移,或者以st ...

  8. Codeforces 543D Road Improvement(DP)

    题目链接 Solution 比较明显的树形DP模型. 首先可以先用一次DFS求出以1为根时,sum[i](以i为子树的根时,满足要求的子树的个数). 考虑将根从i变换到它的儿子j时,sum[i]产生的 ...

  9. Codeforces 543C Remembering Strings(DP)

    题意比较麻烦 见题目链接 Solution: 非常值得注意的一点是题目给出的范围只有20,而众所周知字母表里有26个字母.于是显然对一个字母进行变换后是不影响到其它字符串的. 20的范围恰好又是常见状 ...

随机推荐

  1. 初学python-day5 集合

  2. 用css写三角形

    html部分 <div class="triangle></div> css部分 .triangle{ width:0; height:0; overflow:hid ...

  3. 六个好习惯让你的PCB设计更优

    PCB layout工程师每天对着板子成千上万条走线,各种各样的封装,重复着拉线的工作,也许很多人会觉得是很枯燥无聊的工作内容.看似软件操作搬运工,其实设计人员在过程中要在各种设计规则之间做取舍,兼顾 ...

  4. [CSP-S2021] 回文

    链接: P7915 题意: 给出一个长度为 \(2n\) 的序列 \(a\),其中 \(1\sim n\) 每个数出现了 2 次.有 L,R 两种操作分别是将 \(a\) 的开头或末尾元素加入到初始为 ...

  5. PWN学习之栈溢出

    目录 PWN学习之栈溢出 前言 写bug bug.cpp源码 OD动态调试bug.exe OD调试观察溢出 栈溢出攻击之突破密码验证 x64位栈溢出 PWN学习之栈溢出 前言 我记得我在最开始学编程的 ...

  6. Docker 制作Nginx镜像

    参考文章:https://www.jianshu.com/p/dc4cd0547d1e 镜像的制作方式有两种,一种是下载别人的镜像之后再制作成自己的镜像,一种是从头开始制作自己的镜像 第一种,下载别人 ...

  7. SQL*Loader-704: Internal error: ulconnect: OCIServerAttach [0] ORA-12541: TNS:no listener

    使用/app/oracle/product/11.2.0/bin/sqlldr导入数据报错: 监听没有开启?检查发现监正常 猜测是监听端口不是默认的1521有关系,直接在sid里面加上数据库服务器的i ...

  8. javac 不是内部或外部命令 和 错误 找不到或无法加载主类 的解决方法

    使用package语句与import语句. 实验要求:按实验要求使用package语句,并用import语句使用Java平台提供的包中的类以及自定义包中的类.掌握一些重要的操作步骤. 代码: 模板1: ...

  9. robot_framewok自动化测试--(3)测试项目与测试套件的概念

    测试项目与测试套件的概念 如果你查看当前所创建的项目会发现,"test_project"是一个目录: "test_suit"则是一个 txt 文件: " ...

  10. 记录线上APP一个排序比较引发的崩溃 Comparison method violates its general contract!

    最近在做产品需求的时候上线了一个新的产品需求,给用户多了一种新的排序排序规则,更加方便用户找到自己想要的东西.新版本发布后,QA 给我发了一个 线上崩溃 bug 链接,具体内容如下: 看到上面的链接, ...