ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

cf959 E. Mahmoud and Ehab and the xor-MST(找规律,数学)

2021-12-23 02:04:24  阅读:170  来源: 互联网

标签:xor cf959 lowbit ll MST msb ans sum dp


题意:

n个顶点的完全图,编号为0~n-1,任意两点间的边权为两个点的编号的异或,求最小生成树的边权总和。(仍是普通加和,不是异或和)

思路:

为讨论方便,把输入的n减一。

先写个prim找规律,发现除了0外,每个点 \(i\) 都向 \(i \oplus lowbit(i)\) 连一条边。总和就是 \(ans=\sum\limits_{i=1}^n lowbit(i)\)。

设 \(f(x)\) 表示 \(lowbit(y)=x\) 的 \(y\) 的个数,则 \(ans=\sum\limits _{x=1}^n xf(x)\) 。注意到 \(x\) 只能取 2 的幂,所以 \(ans=\sum\limits _{i=0}^{\lfloor logn\rfloor}2^if(2^i)\) 。

那么 \(f(x)\) 怎么算呢?找规律:\(f(4)=|\{4,12,20,28,\cdots(不能超过n)\}|\),公差为8。事实上 \(f(x)=\lfloor\frac{n-x}{2x}\rfloor+1\)

ll n, ans = 0; cin >> n; n--;
for(ll x = 1; x <= n; x *= 2)
    ans += x * ((n-x) / (2*x) + 1);
cout << ans;

还可以dp,直接嗯找规律:

每个顶点的边:\(1,2,1,4,1,2,1,8,1,2,1,4,\cdots\) ,发现每次把当前数组复制一遍,然后在中间插一个 \(2^i\) 。长度每次乘2加1。即有 \(ans(1)=dp[1]=1\),\(ans(2^{i}-1)=dp[i]=2*dp[i-1]+2^{i-1}\) 。

\(ans(x)=ans(msb(x)) + ans(x\oplus msb(x))\) ,\(msb(x)\) 表示不超过x的最大的2的幂。加号右边递归下去,最终如果 \(n\) 的第 \(i\) 位为1,答案就加上 \(ans(2^i)=ans(2^i-1+1)=ans(2^i-1)+2^i=dp[i]+2^i\)。即第 \(i\) 位的贡献。

ll n, ans = 0; cin >> n; n--;
dp[1] = 1; for(int i = 2; i < 40; i++) dp[i] = dp[i-1]*2 + (1ll<<(i-1));
for(int i = 0; i < 40; i++)
    if((n>>i)&1) ans += dp[i] + (1ll << i);
cout << ans;

标签:xor,cf959,lowbit,ll,MST,msb,ans,sum,dp
来源: https://www.cnblogs.com/wushansinger/p/15721793.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有