「题解」写点 Codeforces 之 0x02

我承认发博客是一件很难的事情,但是为了时间别人我还是自己也发点吧。

神秘并查集。

https://codeforces.com/problemset/problem/2033/E

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
void solve() {
    int n;
    cin >> n;
    DSU dsu(n);
    for (int i = 0; i < n; i ++) {
        int x;
        cin >> x;
        x --;
        dsu.merge(i, x);
    }
    set<int> c;
    for (int i = 0; i < n; i ++) {
        c.insert(dsu.find(i));
    }
    int ans = 0;
    for (auto &x : c)
        ans += (dsu.size(x) + 1) / 2 - 1;
    cout << ans << "\n";
}

神秘交互题。

https://codeforces.com/problemset/problem/2013/C

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
void solve() {
    int n;
    cin >> n;

    auto ask = [&](const string& t) {
        cout << "? " << t << endl;
        int ret;
        cin >> ret;
        if (ret == -1)
            exit(0);
        return ret;
    };

    string ans = "";
    while (ans.size() < n) {
        if (ask(ans + "0")) {
            ans += "0";
            continue;
        }
        if (ask(ans + "1")) {
            ans += "1";
            continue;
        }
        break;
    }

    while (ans.size() < n) {
        if (ask("0" + ans)) {
            ans = "0" + ans;
            continue;
        }
        ans = "1" + ans;
    }
    cout << "! " << ans << endl;
}

神秘位运算。

https://codeforces.com/problemset/problem/2020/C

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
void solve() {
    int b, c, d;
    cin >> b >> c >> d;
    int a = 0;
    int mask = 1;
    for (int i = 0; i < 62; i ++) {
        int bb = !!(b & mask), cc = !!(c & mask), dd = !!(d & mask);
        if (bb and not cc and not dd or not bb and cc and dd) {
            cout << "-1\n";
            return;
        }
        if (bb and cc) {
            a += (1ll - dd) * mask;
        } else {
            a += dd * mask;
        }
        mask <<= 1;
    }
    cout << a << "\n";
}

极其神秘的位运算。

https://codeforces.com/problemset/problem/2057/C

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <bits/stdc++.h>
using namespace std;

#define int long long

void solve(){
    int l, r;
    cin >> l >> r;
    // 固定 a = l, c = r,构造 b
    int b = 0;  // 用来构造 b 的值
    int tp = -1;  // 第一个 l 与 r 不同的位(从高位开始找)
    // 假设数最多 32 位,从 31 到 0
    for(int i = 31; i >= 0; i--){
        if (((l >> i) & 1LL) != ((r >> i) & 1LL)) {
            tp = i;
            break;
        }
    }
    // 注意:题目保证 l < r ,因此 tp 一定不为 -1

    // 1. 对于高于 tp 的位,l 和 r 均相同,直接复制
    for (int i = tp+1; i < 32; i++){
        if((l >> i) & 1LL)
            b |= (1LL << i);
    }
    // 2. 对于从 tp 到 0 的位,先对那些 l 和 r 相同的位,令 b_i = l_i ⊕ 1
    for (int i = tp; i >= 0; i--){
        if (((l >> i) & 1LL) == ((r >> i) & 1LL)){
            // 令 b_i = (l_i XOR 1)
            if (((l >> i) & 1LL) == 0)
                b |= (1LL << i);  // 0^1 = 1
            // 如果 l_i 为 1,则 b_i 取 0;这里 b_i 默认已是 0,所以不用处理
        }
    }
    // 3. 对于从 tp 到 0 的位,处理那些 l 与 r 不同的位:
    for (int i = tp; i >= 0; i--){
        if (((l >> i) & 1LL) != ((r >> i) & 1LL)){
            // 尝试置 1
            b |= (1LL << i);
            // 如果设置后 b 超过或等于 r,则把这一位还原为 0
            if (b >= r)
                b &= ~(1LL << i);
        }
    }
    // 保证最终 l < b < r
    if(b <= l) b = l + 1;
    if(b >= r) b = r - 1;
    
    cout << l << " " << b << " " << r << "\n";
}
 
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int t;
    cin >> t;
    while(t--){
        solve();
    }
    return 0;
}
赣ICP备2024042422号
使用 Hugo 构建
主题 StackJimmy 设计