首页 > 其他分享 >CF1188D Make Equal

CF1188D Make Equal

时间:2022-09-27 17:34:33浏览次数:50  
标签:cnt int text Make Equal CF1188D 进位 位为

假设 \(a\) 数组有序,记 \(\text{cnt}(x)\) 表示 \(x\) 的二进制表示中 \(1\) 的个数。
那么我们就是要找一个 \(x\) 使得 \(\sum_{i=1}^{n}\text{cnt}(x+a_n-a_i)\) 最小。下面令 \(a_i\gets a_n-a_i\)。
我们考虑 \(x+a_i\) 的第 \(k\) 位。这一位的决策与下面的东西有关:

  • \(x\) 这一位填不填 \(1\)(要决策的东西)
  • \(a_i\) 这一位是不是 \(1\)
  • 前一位的进位情况

棘手的是第三种情况,如果暴力记录,有 \(2^n\) 种情况。但是注意到,由于 \(x\) 是相同的,那么 \(a_i\) 前 \(k-1\) 位越大越容易进位。如果将所有 \(a_i\) 按照 \(a_i\bmod 2^k\) 的大小从大到小排序,则最后进位的一定是一段前缀,那么就可以 DP 了。
设 \(f_{i,j}\) 表示前 \(i\) 位,有 \(j\) 个数进位。转移有如下四种情况:

  • \(x+a_k\) 在第 \(i\) 位没有进位,\(a_k\) 的 \(i+1\) 位为 \(1\)。
  • \(x+a_k\) 在第 \(i\) 位没有进位,\(a_k\) 的 \(i+1\) 位为 \(0\)。
  • \(x+a_k\) 在第 \(i\) 位进位,\(a_k\) 的 \(i+1\) 位为 \(1\)。
  • \(x+a_k\) 在第 \(i\) 位进位,\(a_k\) 的 \(i+1\) 位为 \(0\)。

枚举 \(x\) 的第 \(i+1\) 位:

  • 该位为 \(1\),第一、三、四种会进位,第二、三类 \(i+1\) 位为 \(1\)。
  • 该位为 \(0\),第三类会进位,第一、四类 \(i+1\) 位为 \(1\)。

Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100005;
int n;
ll a[N];
int f[62][N];
int id[N];
int K;
int sum[2][N];

bool cmp(int x, int y) {
	return (a[x] & ((1ll << K) - 1)) < (a[y] & ((1ll << K) - 1));
}

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], id[i] = i;
	memset(f, 0x3f, sizeof f); f[0][0] = 0;
	for (int k = 0; k <= 60; ++k) {
		K = k;
		sort(id + 1, id + n + 1, cmp);
		for (int i = 1; i <= n; ++i) {
			sum[0][i] = sum[0][i - 1],
			sum[1][i] = sum[1][i - 1];
			++sum[a[id[i]] >> k & 1][i];
		}
		for (int i = 0; i <= n; ++i) {
			int x, y;
			x = sum[1][n - i] + sum[0][n] - sum[0][n - i], y = sum[1][n] - sum[1][n - i];
			f[k + 1][y] = min(f[k + 1][y], f[k][i] + x);
			x = sum[0][n - i] + sum[1][n] - sum[1][n - i], y = n - sum[0][n - i];
			f[k + 1][y] = min(f[k + 1][y], f[k][i] + x);
		}
	}
	printf("%d", f[61][0]);
	return 0;
}

标签:cnt,int,text,Make,Equal,CF1188D,进位,位为
From: https://www.cnblogs.com/Kobe303/p/16735311.html

相关文章

  • 洛谷 CF1257F Make Them Similar 灰 题解
    前言本题解采用折半搜索算法完成,对于不打算用这种方法的同学,这篇题解可能会浪费你人生中宝贵的十几分钟。思路此题似乎找不出什么好的性质,那么考虑暴力。发现\(x,a\)......
  • go之new和make
    我们先来看一个例子:funcmain(){ vara*int *a=100 fmt.Println(*a) varbmap[string]int b["沙河娜扎"]=100 fmt.Println(b)}执行上面的代码会引......
  • 晶体、分子结构软件:CrystalMaker for Mac
    晶体结构软件CrystalMakerformac创建、显示和操作各种晶体和分子结构,CrystalMakerMac版便捷、灵活,能够容易的载入结构数据并产生壮观的,相片型的图形,戴上红/蓝眼镜,还可......
  • Cmake安装
    进入Cmake官网根据自己需要选择安装包下载后双击安装进入安装界面,点击【Next】同意协议,点击【Next】将Cmake添加进用户变量点击【Next注意:选择......
  • vscode + mingw + cmake
    安装cmake-3.24.2-windows-x86_64.msi勾选添加到环境变量勾选CreateCmakeDesktopIcon需要安装mingw-get-setup.exe在windows中cmake..替换成cmake-G"M......
  • CMake使用指南
    单文件编译添加版本号project(xxxVERSION0.1.0)指定C++版本set(CMAKE_CXX_STANDARD11)set(CMAKE_CXX_STANDARD_REQUIREDTrue)多文件编译将所有头文件放到Inc......
  • OpenCV CMake windows下 C++ OpenCV配置及x86编译(傻瓜式教程)
    本傻瓜教程需要的环境如下:IDE:vs2015或vs2017, windows10或11关于vs的版本,个人觉得不管是社区版个人版还是企业版,对于我们工作学习的个人来说都一样,......
  • CMAKE的学习
    下面我们来介绍CmakeCmake我们着重介绍一下CMAKE,是因为CMAKE现在用的人比MAKEFILE多一些,也更好理解,编写一些。1安装cmake1.1卸载已经安装的旧版的CMAKE【非必需】a......
  • make编译错误
    报错截图:1checkingforpcre-config...false2configure:error:pcre-configforlibpcrenotfound.PCREisrequiredandavailablefromhttp://pcre.org/解......
  • gamemaker学习记录001
    截屏功能:截屏函数:screen_save获取时间戳:date_get_second_of_year(date_current_datetime())完整的截屏:if(keyboard_check(ord("Q"))){screen_save(string(date_......