#位运算#CF959E Mahmoud and Ehab and the xor-MST

题目

\(n\)个点的完全图标号为\([0,n-1]\),\(i\)\(j\)连边权值为\(i\: xor\:j\),求MST的值


分析

考虑MST有两种解法一种是Prim一种是Kruskal,Prim应该更好理解。
既然是一个完全图,那么每次新加入一个点,只要找到与它连边的边权最小就可以了
所以题目就转换成每次找到一个\(j<i\),最小化\(i\: xor \: j\)
那尽量让\(j\)的高位与\(i\)的高位一致,只改变最后一位即可,
由于异或的运算相同即零不同即一,既然要让\(j<i\),那么让\(j=i\: xor \: lowbit(i)\)才是最优的,
因为若边权\(<lowbit(i)\),那么\(j>i\),若边权\(>lowbit(i)\),为何不令边权\(=lowbit(i)\)
所以题目就转换成\(\sum_{i=1}^{n-1} lowbit(i)\)
这个\(O(\log_2n)\)求就可以了
考虑哪些数对\(2^k\)有贡献,那就是\(2^k\)的倍数且非\(2^{k+1}\)的倍数即可,那就是

\[\lfloor\frac{n}{2^k}\rfloor-\lfloor\frac{n}{2^{k+1}}\rfloor=\lceil\frac{n}{2^{k+1}}\rceil \]


代码

#include <cstdio>
#define rr register
using namespace std;
typedef long long lll; lll ans,n;
signed main(){
	scanf("%lld",&n); --n; 
	for (rr lll two=1;n;n>>=1)
	    ans+=((n+1)>>1)*two,two<<=1;
	return !printf("%lld",ans);
}
posted @ 2020-11-03 16:41  lemondinosaur  阅读(53)  评论(0)    收藏  举报