首页 > 其他分享 >Codeforces 1188D Make Equal

Codeforces 1188D Make Equal

时间:2023-06-10 11:25:18浏览次数:34  
标签:bitcount int Make Equal Codeforces sum operatorname 进位 位为

设最终所有数变为的值为 \(u\),\(\operatorname{bitcount}(x)\) 为 \(x\) 二进制上为 \(1\) 的位数,由题可得答案即为 \(\sum\limits_{i = 1}^n \operatorname{bitcount}(u - a_i)\)。
此时让 \(a_i\) 从小到大排序,答案即为 \(\sum\limits_{i = 1}^n \operatorname{bitcount}(u - a_n + (a_n - a_i))\)。
令 \(v = u - a_n, a_i = a_n - a_i\),答案即为 \(\sum\limits_{i = 1}^n \operatorname{bitcount}(v + a_i)\)。

然后可以想到类似于数位 DP 枚举 \(v\) 二进制每位的数字一步一步往后推得到答案。
考虑每一步需要什么条件:
第 \(i\) 位,枚举得来;为 \(0\) 或 \(1\),同理;\(a_j\) 第 \(i\) 为是否为 \(1\),能 \(O(1)\) 求出;\(a_j\) 第 \(i - 1\) 位有没有进位,这个好像有点难解决,似乎只能 \(O(2^n)\)。
其实有一个比较贪心的想法,就是 \(a_j\) 前 \(i - 1\) 位(即 \(a_j\bmod 2^i\))越大就越有可能进位,所以只需要在处理第 \(i\) 位时按 \(a_j\bmod 2^i\) 从大至小排序,这样就只用枚举前缀了,优化到了 \(O(n)\)。

设 \(f_{i, j}\) 为第 \(i\) 位产生了 \(j\) 个进位的答案最小值,现在考虑由 \(f_{i}\) 推到 \(f_{i + 1}\)。
设 \(a_{1}\sim a_{n}\) 第 \(i\) 位一共有 \(x\) 个 \(1\),\(a_1\sim a_{j}\) 第 \(i\) 位一共有 \(y\) 个 \(1\),于是可以得到:

  1. 第 \(i\) 位为 \(1\) 且进位,个数为 \(y\);
  2. 第 \(i\) 位为 \(0\) 且进位,个数为 \(j - y\);
  3. 第 \(i\) 位为 \(1\) 且不进位,个数为 \(x - y\);
  4. 第 \(i\) 位为 \(0\) 且不进位,个数为 \(n - j - (x - y)\)。

考虑 \(v\) 第 \(i\) 位不同取值会有什么贡献:

  1. 为 \(0\),则 1 情况会进位,23 情况会增加 \(1\) 的贡献,\(f_{i, j} + (j - y) + (x - y)\rightarrow f_{i + 1, y}\);
  2. 为 \(1\),则 123 情况会进位,14 情况会增加 \(1\) 的贡献,\(f_{i, j} + y + (n - j - (x - y))\rightarrow f_{i + 1, y +(j - y) + (x - y)}\)。

时间复杂度 \(O(n\log_2 n\log_2 \max\{a_i\})\)。

// lhzawa(https://www.cnblogs.com/lhzawa/)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, M = 60;
long long a[N];
int f[M + 2][N];
int main() {
	int n;
	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];
	}
	// for (int i = 1; i <= n; i++) {
	// 	printf("%lld ", a[i]);
	// }
	// printf("\n");
	memset(f, 0x3f, sizeof(f));
	f[0][0] = 0;
	for (int i = 0; i < M; i++) {
		sort(a + 1, a + n + 1, [&i](long long x, long long y) {
			return (x & ((1ll << i) - 1)) > (y & ((1ll << i) - 1)); 
		});
		int x = 0;
		for (int j = 1; j <= n; j++) {
			x += ((a[j] >> i) & 1);
		}
		int y = 0;
		for (int j = 0; j <= n; j++) {
			// printf("%d ", f[i][j]);
			y += ((a[j] >> i) & 1);
			function<void (int&, int)> Min = [](int& a, int b) -> void {
				a = min(a, b);
				return ;
			};
			Min(f[i + 1][(y) + (j - y) + (x - y)], f[i][j] + y + (n - j - (x - y)));
			Min(f[i + 1][y], f[i][j] + (j - y) + (x - y));
		}
		// printf("\n");
	}
	printf("%d\n", f[M][0]);
	return 0;
}

标签:bitcount,int,Make,Equal,Codeforces,sum,operatorname,进位,位为
From: https://www.cnblogs.com/lhzawa/p/17470946.html

相关文章

  • Makefile基础教程(变量的高级主题,变量的拓展)
    (文章目录)前言本篇文章将给大家讲解一下变量的高级主题,变量的拓展,这些主题可以让你更加灵活地编写和维护Makefile。一、变量值的替换1.简单替换变量替换语法格式:$(var:a=b)其中,a可以是一个字母,表示var中每个单词结尾的这个字母。b则是替换的字符串。它会替换每个单......
  • 构建编译dockerfile docker build报错make: uname: Operation not permitted
    报错信息:查看docker版本#docker-vDockerversion1.13.1,build7d71120/1.13.1在dockerfile中我使用的基础镜像为FROMalpine:3.16.5解决办法是升级docker或者降低Alpine的版本,我这边选择升级docker版本卸载现有docker版本#yum-yremove$(rpm-qa|grepdocker......
  • Atcoder ARC100D Equal Cut
    发现是\(3\)个断点且数据范围的\(n\le2\times10^5\),根据2022CSP-SA留下的心理阴影不难想到可以枚举中间的那个点的同时移动左右两个端点。考虑如何移动,已知现在在枚举中间的断点\(i\),则现在被分为了两部分\(1\simi\)和\(i\simn\),因为要使极差最小,那就先可以让每一......
  • Codeforces 1626 C
    1626C题意抽象出题意:给出n个区间的结尾以及它的区间长度,然后每一段连续区间的贡献为\(\sum_{i=1}^{len}i\),求总贡献。思路处理出每个区间的开头结尾,排序后处理每个连续区间就行了。代码voidsolve(){ cin>>n; for(inti=1;i<=n;i++)cin>>p[i].second; for(inti=1,......
  • Codeforces 1514 C
    1514C题意给出一个数n,求[1,2,3...n-1]的某个最长子序列,这个子序列的元素乘积模n余1。思路这是个思维题,一个数学公式\[x\equiv1(modn)\rightarrowkx\equivk(mod kn)\]所以子序列中的元素与\(n\)互质,累乘结果模\(n\)后如果不是1,那么将序列中等于结果的元素去......
  • equals方法
    //Student3类publicclassStudent3{privateStringname;privateintage;publicStudent3(){super();}publicStudent3(Stringname,intage){this.name=name;this.age=age;}publicStringgetName(){......
  • Codeforces 1515 B
    1515B题意有n只袜子(n为偶数),但左袜子有L只,右袜子有R只,每只袜子的颜色为\(C_i\),可以进行以下操作:换袜子的方向、或者将袜子变色,问进行多少次操作后变成(n/2)对袜子思路很曲折,想了很久后终于想清楚,排除配对的袜子后,对于某类袜子\(i\),剩下\(c\geq2\)(假设剩下的是右边)只,它的配对......
  • 一次windows下使用cmake遇到的问题
    背景在windows下的cmake和mingw提供的make,在windows环境下进行了简单尝试,结果发现make的时候失败:#include<iostream>intmain(){std::cout<<"Hello,makefile."<<std::endl;return0;}CMakeList如下:project(test)add_executable(testtest.cpp)非常......
  • Kettle连接MySQL报错:Driver class 'org.gjt.mm.mysql.Driver' could not be found, ma
    在Windows系统里面安装kettle后打算连接MySQL的时候突然报错错误连接数据库[wanghui]:org.pentaho.di.core.exception.KettleDatabaseException:ErroroccurredwhiletryingtoconnecttothedatabaseDriverclass'org.gjt.mm.mysql.Driver'couldnotbefound,mak......
  • CodeForces - 658A Bear and Reverse Radewoosh (模拟)水
    TimeLimit: 2000MS MemoryLimit: 262144KB 64bitIOFormat: %I64d&%I64uCodeForces-658ABearandReverseRadewooshSubmit StatusDescriptionLimakandRadewoosharegoingtocompeteagainsteachotherintheupcomingalgorithmiccontest.Theyareequ......