Codeforces Round #736 (Div. 2)【ABCD】

比赛链接:https://codeforces.com/contest/1549

A. Gregor and Cryptography

题解

构造。

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        int p;
        cin >> p;
        cout << 2 << ' ' << (p - 1) << "\n";
    }
    return 0;
}

B. Gregor and the Pawn Game

题解

贪心,尽可能地靠一边放。

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        vector<string> MP(2);
        for (int i = 0; i < 2; i++) {
            cin >> MP[i];
        }
        vector<bool> vis(n);
        for (int i = 0; i < n; i++) {
            if (MP[1][i] == '0') {
                continue;
            }
            if (i - 1 >= 0 and MP[0][i - 1] == '1' and not vis[i - 1]) {
                vis[i - 1] = true;
            } else if (MP[0][i] == '0' and not vis[i]) {
                vis[i] = true;
            } else if (i + 1 < n and MP[0][i + 1] == '1' and not vis[i + 1]) {
                vis[i + 1] = true;
            }
        }
        cout << count(vis.begin(), vis.end(), true) << "\n";
    }
    return 0;
}

C. Web of Lies

题解

类似拓扑排序的思想,将无向边转化为有向边,假设由较小点指向较大点,每次询问即统计出度为 0 的点。

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    vector<int> out(n);
    set<int> st;
    auto opt = [&](bool add) {
        int u, v;
        cin >> u >> v;
        --u, --v;
        out[min(u, v)] += add ? 1 : -1;
        st.erase(u), st.erase(v);
        if (out[u] == 0) {
            st.insert(u);
        }
        if (out[v] == 0) {
            st.insert(v);
        }
    };
    for (int i = 0; i < m; i++) {
        opt(true);
    }
    for (int u = 0; u < n; u++) {
        if (out[u] == 0) {
            st.insert(u);
        }
    }
    int q;
    cin >> q;
    while (q--) {
        int op;
        cin >> op;
        if (op == 1) {
            opt(true);
        } else if (op == 2) {
            opt(false);
        } else {
            cout << st.size() << "\n";
        }
    }
    return 0;
}

D. Integers Have Friends

题解

不妨先考察较小的情况,如果两个数 \(a\)​ 和 \(b\)​ 同余,它们与余数 \(m\)​ 的关系。

假设 \(a \lt b\) ,易得:

\(a = a\)

\(b = a + (b - a)\)

\(a\)\(b\)\(m\) 取余即:

\(a \bmod m\)

\(a \bmod m + (b - a) \bmod m\)

所以,若 \(a\)\(b\) 同余,那么 \((b - a) \bmod m = 0\) ,即 \(m\)\((b - a)\)​ 的因子。

推广到 \(n\)​​​ 个数同余的情况,可以看作 \(n - 1\)​​​ 对相邻的数, \(m\)​​​ 同为 \(n - 1\)​ 对相邻数之差的因子。

所以,问题即转化成了在 \(b_i = |a_{i + 1} - a_i|\) 中寻找 \(gcd \gt 1\)​​ 的最长区间。

可以枚举区间的左端点,然后用双指针或二分结合 \(st\)​​​ 表计算区间的右端点。

代码一

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        vector<long long> a(n);
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
        if (n == 1) {
            cout << 1 << "\n";
            continue;
        }
        vector<long long> b(n - 1);
        for (int i = 0; i < n - 1; i++) {
            b[i] = abs(a[i + 1] - a[i]);
        }
        const int logn = __lg(n) + 1;
        vector<vector<long long>> spt(n - 1, vector<long long> (logn));
        for (int i = 0; i < n - 1; i++) {
            spt[i][0] = b[i];
        }
        for (int j = 1; j < logn; j++) {
            for (int i = 0; i + (1 << j) - 1 < n - 1; i++) {
                spt[i][j] = gcd(spt[i][j - 1], spt[i + (1 << (j - 1))][j - 1]);
            }
        }
        auto query = [&](int l, int r) {
            int ep = __lg(r - l + 1);
            return gcd(spt[l][ep], spt[r - (1 << ep) + 1][ep]);
        };
        int ans = 0;
        for (int i = 0, j = -1; i < n - 1; i++) {
            while (j + 1 < n - 1 and query(i, j + 1) > 1) {
                ++j;
            }
            if (i <= j) {
                ans = max(ans, j - i + 1);
            }
            j = max(j, i);
        }
        cout << ans + 1 << "\n";
    }
    return 0;
}

代码二

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        vector<long long> a(n);
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
        if (n == 1) {
            cout << 1 << "\n";
            continue;
        }
        vector<long long> b(n - 1);
        for (int i = 0; i < n - 1; i++) {
            b[i] = abs(a[i + 1] - a[i]);
        }
        const int logn = __lg(n) + 1;
        vector<vector<long long>> spt(n - 1, vector<long long> (logn));
        for (int i = 0; i < n - 1; i++) {
            spt[i][0] = b[i];
        }
        for (int j = 1; j < logn; j++) {
            for (int i = 0; i + (1 << j) - 1 < n - 1; i++) {
                spt[i][j] = gcd(spt[i][j - 1], spt[i + (1 << (j - 1))][j - 1]);
            }
        }
        auto query = [&](int l, int r) {
            int ep = __lg(r - l + 1);
            return gcd(spt[l][ep], spt[r - (1 << ep) + 1][ep]);
        };
        int ans = 0;
        for (int i = 0; i < n - 1; i++) {
            int l = i, r = n - 2;
            while (l < r) {
                int mid = (l + r + 1) / 2;
                if (query(i, mid) > 1) {
                    l = mid;
                } else {
                    r = mid - 1;
                }
            }
            if (query(i, r) > 1) {
                ans = max(ans, r - i + 1);
            }
        }
        cout << ans + 1 << "\n";
    }
    return 0;
}

参考

https://oi-wiki.org/ds/sparse-table/

https://codeforces.com/contest/1548/submission/124526158

posted @ 2021-08-03 18:20  Kanoon  阅读(59)  评论(0编辑  收藏  举报