题目描述
在无垠的宇宙中,有 n 个星球,第 i 个星球有权值
v
i
v_i
vi。
由于星球之间距离极远,因此想在有限的时间内在星际间旅行,就必须要在星球间建立传送通道。
任意两个星球之间均可以建立传送通道,不过花费并不一样。第 i 个星球与第 j 个星球的之间建立传送通道的花费是
lowbit
(
v
i
⊕
v
j
)
\text{lowbit}(v_i\oplus v_j)
lowbit(vi⊕vj),其中
⊕
\oplus
⊕ 为二进制异或,而
lowbit
(
x
)
\text{lowbit}(x)
lowbit(x) 为 x 二进制最低位 1 对应的值,例如
lowbit
(
5
)
=
1
,
lowbit
(
8
)
=
8
\text{lowbit}(5)=1,\text{lowbit}(8)=8
lowbit(5)=1,lowbit(8)=8。特殊地,
lowbit
(
0
)
=
0
\text{lowbit}(0)=0
lowbit(0)=0。
牛牛想在这 n 个星球间穿梭,于是――你需要告诉 牛牛,要使这 n 个星球相互可达,需要的花费最少是多少。
输入描述:
第一行,一个正整数 n 。
第二行,n 个非负整数
v
1
,
v
2
,
…
,
v
n
v_1,v_2,\dots,v_n
v1,v2,…,vn 。
保证
1
≤
n
≤
2
×
1
0
5
,
0
≤
v
i
<
2
30
1\leq n\leq 2\times 10^5 ,0\leq v_i < 2^{30}
1≤n≤2×105,0≤vi<230。
输出描述:
输出一行,一个整数表示答案。
输入
2
1 2
输出
1
说明
1 、 2 \text{}1、2 1、2 号点之间建立通道, v 1 ⊕ v 2 = 3 , lowbit ( 3 ) = 1 v_1 \oplus v_2=3, \text{lowbit}(3)=1 v1⊕v2=3,lowbit(3)=1
题解
-
首先将权值去重(权值相等的点连接代价为 0 ),设去重后有 m 个点,接下来找到最小的二进制位 k ,满足存在 v i v_i vi 的这个二进制位是 0 且存在 v j v_j vj 的这个二进制位是 1 ,答案就是 2 k × ( m − 1 ) 2^k\times (m-1) 2k×(m−1)(相当于所有这位是 0 的点与 j 点连边,是 1 的点与 i 点连边)。
-
排序和去重以外时间复杂度 O ( n + log V ) O(n+\log V) O(n+logV) ,没有卡 O ( n log V ) O(n\log V) O(nlogV) ,好像两个 log \log log 也过了。
AC-Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int maxn = 2e5 + 5;
int a[maxn];
int main() {
ios;
int n; cin >> n; ll ans = 0;
for (int i = 0; i < n; ++i) cin >> a[i];
sort(a, a + n);
int tot = unique(a, a + n) - a; // 去重
int v1 = 0, v0 = 0xffffffff;
for (int i = 0; i < tot; ++i) { // 取所有的每个位置的 0和1
v1 |= a[i];
v0 &= a[i];
}
int k = v1 ^ v0; // 得到既有0又有1的位置
int i = 0;
while (k > 0) { // 如果存在计算,不存在的话代价就是0
int c = 1 << i++;
if (k & c) {
ans = c * (tot - 1);
break;
}
}
cout << ans << endl;
}