Codeforces.959E.Mahmoud and Ehab and the xor-MST(思路)

题目链接

(Description)

  有一张(n)个点的完全图,从(0)(n-1)标号,每两点(i,j)间的边权为(ioplus j)。求其最小生成树边权之和。

(Solution)

  为方便,以下点从(0)(n)编号。
  每个点(x)应和(xoplus lowbit(x))相连,边权为(lowbit(x))(lowbit(x))会和(0)相连,所以一定能构成树),所以答案为(sum_{i=1}^nlb(i))
  继续优化。注意到(lb(i))一定是某个2次幂,所以令(f(i))表示(1leq xleq n)且满足(lb(x)=i)(x)的个数,则答案为(sum_{i=1}^nf(i) imes i (f(i)>0)=sum_{i=0}^{lfloorlog n floor}f(2^i) imes 2^i)
  (f(i))显然可以用数位DP算,但是太麻烦了。。
  一些满足(lb(i)=x)的数,它们间隔至少是(2x)。比如(x=(100)_2),则(i=100,1100,10100...)(相差(1000))。所以(f(x)=lfloorfrac{n-x}{2x} floor+1 (1leq xleq n,x=2^y))


  还有DP求(sum_{i=1}^nlb(i))的做法,好长啊...先不看了。
Codeforces.959E.Mahmoud and Ehab and the xor-MST(思路)


#include <cstdio>

int main()
{
	long long n,res=0;
	scanf("%I64d",&n); --n;
	for(long long x=1; x<=n; x<<=1)
		res+=x*((n-x)/(x<<1)+1);
	printf("%I64d
",res);

	return 0;
}