進程和線程 進程 一個程式,如QQ.exe,是程式的集合 一個進程往往可以包含多個線程,至少包含一個 java預設有兩個線程,GC垃圾回收線程和Main線程 線程:一個進程中的各個功能 java無法真正的開啟線程,因為java是運行在虛擬機上的,所以只能通過C++,通過native本地方法調用C++ ...
題目鏈接
題目大意
給定兩組序列 \(a\) \(b\),長度為 \(n\) ,現有一新序列 \(c\),長度也為 \(n\) 。
其中,\(c_i = a_i \oplus b_i\) 。
定義 \(f(a,b) = c_1\&c_2\&……\&c_n\)。
現在你可以隨意編排 \(b\) 序列的順序,求 \(f(a,b)\) 的最大值。
思路
以下位運算均是二進位。
由於按位與的運算結果是越來越小的,考慮從高位往低位貪心。
將結果的其中一位定為1之後,有一些序列 \(b\) 中的元素的位置就被定下來了。
所以我們要從高位往低位貪心,有一位可以置為1,就把它置為1.
具體做法:暴力枚舉,時間複雜度\(O(nlognlogA)\),其中 \(A\) 是輸入序列的最大值。
void solve() {
cin >> n;
a = vector<int> (n);
b = vector<int> (n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
for (int i = 0; i < n; ++i) {
cin >> b[i];
}
auto check = [&](int ans){
//ans是一個2的整次冪
map<int,int> cnt;
//下麵兩個for是 判斷該位上、a序列的1和b序列的0的個數是否相等。
for(auto x:a) cnt[x & ans] += 1;
for(auto x:b) cnt[~x & ans] -= 1;
bool ok = true;
//如果有1,證明不等,ok置為false
for(auto [u,v] : cnt){
ok &= v == 0;
}
return ok;
};
int ans = 0;
for(int j = 30; j >= 0; --j){
//從高位向低位檢查。
//寫博客的時候的思考:如何把之前的已經確定了的1保存下來
//答:其實就保存在ans中。
if(check(ans | (1ll << j))){
ans |= 1 << j;
}
}
cout << ans << '\n';
}