Codeforces Round #696 (Div. 2)

Codeforces Round #696 (Div. 2)

A - Puzzle From the Future

贪心, 让长度最长, 每次试 +1,

int main() {
    IOS;
    for (cin >> _; _; --_) {
        string s; cin >> n >> s; m = -1;
        for (int i = 0; i < n; ++i) {
            int c = s[i] - '0';
            if (c + 1 != m) s[i] = '1', m = c + 1;
            else s[i] = '0', m = c;
        }
        cout << s << '\n';
    }
    return 0;
}

B - Different Divisors

1, a, b, a * b

a, b为质数, 且 a - 1 >= d, b - a >= d即可

int prime[N], tot;
bool v[N];
 
void init() {
    for (int i = 2; i <= 2e6; ++i) {
        if (!v[i]) prime[++tot] = i;
        for (int j = 1; j <= tot && prime[j] <= 2e6 / i; ++j) {
            v[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
        }
    }
}
 
int main() {
    IOS; init();
    for (cin >> _; _; --_) {
        cin >> n; ll ans = *lower_bound(prime + 1, prime + tot + 1, 1 + n);
        cout << (ans * (*lower_bound(prime + 1, prime + tot + 1, ans + n))) << '\n';
    }
    return 0;
}

C - Array Destruction

枚举哪个数和最大数一起消去就好, 在模拟判断是否满足, 听说有人是 \(O(n^3)\), 那就没啥算法了, 就是枚举模拟题意

int s[N];
 
bool work(multiset<int> q1, int id, vector<PII>& x) {
    int a = *q1.begin(); q1.erase(q1.begin()); q1.erase(q1.find(-s[id]));
    x.pb({ -a, s[id] }); bool f = 1;
    for (int i = 1; i < n && f; ++i) {
        int mx = *q1.begin(); q1.erase(q1.begin());
        auto it = q1.find(a - mx);
        if (it == q1.end()) f = 0;
        else x.pb({ -mx, -*it }), q1.erase(it), a = mx;
    }
    if (f) return 1; vector<PII>().swap(x);
    return 0;
}
 
int main() {
    IOS;
    for (cin >> _; _; --_) {
        multiset<int> q1; vector<PII> y; bool f = 0;
        cin >> n; rep(i, 1, n * 2) cin >> s[i], q1.insert(-s[i]); sort(s + 1, s + 1 + n * 2);
        for (int i = 1; i < n * 2 && !f; ++i) f = work(q1, i, y);
        if (f) {
            cout << "YES\n" << y[0].fi + y[0].se << '\n';
            for (auto& i : y) cout << i.fi << ' ' << i.se << '\n';
        }
        else cout << "NO\n";
    }
    return 0;
}

D - Cleaning

差分, 最左边的石子只能靠第2堆消去, 以此类推

a[1] - a[1], (a[2] - a[1]) - (a[2] - a[1]), (a[3] - a[2] + a[1]) - (a[3] - a[2] + a[1]), ... , (a[n] - a[n - 1] + a[n - 2] - ... + \((-1)^{n - 1 \& 1}\) * a[1]) - (a[n] - a[n - 1] + a[n - 2] - ... + \((-1)^{n - 1 \& 1}\) * a[1])

最终目标是所有 b[i] = a[i] - a[i- 1] + a[i - 2] - ... + \((-1)^{i - 1 xor 1}\) * a[1] >= 0 且 b[n] = 0

考虑交换 i 和 i + 1, 那么 b[1~i-1] >= 0, 且 b[i] += a[i + 1] - a[i] >= 0, 且 i + 1 ~ n, b[i + 2k + 1] -= 2 * (a[i + 1] - a[i]), b[i + 2k] += 2 * (a[i + 1] - a[i])

所以我们还要预处理 b[i], b[i + 2], ..., b[n - i & 1 ? n : n - 1] 之间的最小值

这样就是 线性 枚举交换 i 和 i + 1, 判断是否可行即可

int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n; vector<ll> a(n + 1), b(n + 1), c(n + 1);
        rep (i, 1, n) cin >> a[i], b[i] = a[i];
        bool f = 1;
        rep (i, 1, n) c[i] = b[i] -= b[i - 1], f = f & (b[i] >= 0);
        f = f & b[n] == 0;
        per (i, n - 2, 1) umin(c[i], c[i + 2]);
        rep (i, 1, n - 1) {
            if (b[i - 1] < 0 || f) break;
            int t = a[i + 1] - a[i];
            if (b[i] + t < 0 || c[i + 1] - 2 * t < 0 || (i + 2 <= n && c[i + 2] + 2 * t < 0)) continue;
            if (b[n] + 2 * (n - i & 1 ? -t : t) == 0) f = 1; 
        }
        cout << (f ? "YES\n" : "NO\n");
    }
    return 0;
}
posted @ 2021-01-24 23:54  洛绫璃  阅读(71)  评论(0编辑  收藏  举报