Codeforces Round 885 (Div. 2)

发布时间 2023-07-18 17:08:57作者: PHarr

A. Vika and Her Friends

枚举所有的点,判断是否存在点与Vika的距离和其他 k 个人的距离的奇偶性不同。

#include <bits/stdc++.h>

using namespace std;

#define int long long

const int mod = 998244353;

void solve() {
    int n, m, k, sx, sy;
    cin >> n >> m >> k >> sx >> sy;
    vector<int> x(k), y(k);
    for (int i = 0; i < k; i++)
        cin >> x[i] >> y[i];
    for (int i = 1, p, f; i <= n; i++)
        for (int j = 1; j <= m; j++) {
            p = (abs(i - sx) + abs(j - sy)) % 2, f = 1;
            for (int l = 0; f && l < k; l++) {
                int q = (abs(i - x[l]) + abs(j - y[l])) % 2;
                if (p == q) f = 0;
            }
            if (f) {
                cout << "YES\n";
                return;
            }
        }
    cout << "NO\n";
    return;
}

int32_t main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int t;
    cin >> t;
    while (t--)
        solve();
    return 0;
}

B. Vika and the Bridge

预处理出所有的数出现的位置,然后枚举数,找到最大的间隔在间隔的最中间的位置插入一个,然后在统计出最大间隔即可。所有数字的最大间隔最小就是答案。

#include <bits/stdc++.h>

using namespace std;

#define int long long

const int mod = 998244353;

void solve() {
    int n, k;
    cin >> n >> k;
    vector<vector<int>> a(k + 1, vector<int>(1, 0));
    for (int i = 1, x; i <= n; i++)
        cin >> x, a[x].push_back(i);
    for (int i = 1; i <= k; i++)
        a[i].push_back(n + 1);
    int res = INT_MAX;
    for( const auto & v : a ){
        multiset<int> s;
        for( int i = 1 ; i < v.size() ; i ++ ){
            s.insert( v[i] - v[i-1] - 1);
            if( s.size() > 2 ) s.erase( s.lower_bound(*s.begin()) );
        }
        if( s.empty() ) continue;
        int x = (*s.rbegin());
        s.erase(s.lower_bound(x));
        x -- , s.insert( x/2 ) , s.insert( (x+1) / 2 );
        res = min( res , *s.rbegin());
    }
    cout << res << "\n";
    return;
}

int32_t main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int t;
    cin >> t;
    while (t--)
        solve();
    return 0;
}

C. Vika and Price Tags

我们只看一对数,当出现了某个数为0 的情况时,就会开始一个大小为 3 的循环。

所以我们要计算第一次\(a\)变为\(0\)需要消耗次数,模三后如果所有的答案都相同则输出YES

显然我们不可以去暴力的计算消耗次数,但是发现\(a>2b\)时,会出现\((a,b)->(b,a-b)->(a-b,a-2b)->(a-2b,b)\)刚好也是三次,所以可以直接对\(2b\)取模就可以快速变小。

#include <bits/stdc++.h>

using namespace std;

#define int long long

void solve() {
    int n;
    cin >> n;
    vector<int> a(n), b(n);
    for (auto &i: a) cin >> i;
    for (auto &i: b) cin >> i;
    for (int i = 0, t, c, last = -1; i < n; i++) {
        if (a[i] == 0 && b[i] == 0) continue;
        t = 0;

        while (a[i] != 0) {
            if (b[i] != 0 && a[i] > 2 * b[i]) a[i] %= 2 * b[i];
            else c = abs(a[i] - b[i]), a[i] = b[i], b[i] = c, t = (t + 1) % 3;
        }
        if (last == -1) last = t;
        else if (last != t) {
            cout << "NO\n";
            return;
        };
    }
    cout << "YES\n";
}

int32_t main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int T;
    cin >> T;
    while (T--)
        solve();
    return 0;
}

D. Vika and Bonuses

很显然,可以想到一定是先执行s+=s%10,再求和。

我们仅看个位数,发现

\[0\rightarrow 0\\ 2 \rightarrow 4 \rightarrow 8 \rightarrow6\rightarrow2 \]

\(0\)没有变化,其他偶数在进行大小为\(4\)的循环,且一个循环可以增加\(20\)

再看其他情况

\[1\rightarrow2\\ 3\rightarrow6\\ 5\rightarrow0\\ 7\rightarrow4\\ 9\rightarrow8\\ \]

只要走一步,要么是\(0\),要么进入循环。

假设我们一开始先操作\(y=4x+i,i\in\{0,1,2,3\}\)

则总和为\(s’\times(k-y)\)。其中\(s’\)是操作\(x\)次后的结果,会发现大致符合单峰函数,似乎可以进行三分,但是样例就会发现不是完全符合三分的。

但是如果\(s’\)是操作\(i\)次后结果,则总和为\((s’+20x)-(k-4x-i)\)\(i\)固定时,完全满足三分。所以可以枚举\(i\)然后三分\(x\)即可。

#include <bits/stdc++.h>

using namespace std;

#define int long long

void solve() {
    int s, k, res;
    cin >> s >> k;
    res = s * k;

    s += s % 10, k--;
    res = max(res, s * k);

    if (s % 10 != 0) {
        auto f = [s, k](int x) {
            if (x > k) return 0ll;
            int a = k - x, b = s;
            b += (x / 4) * 20ll, x %= 4ll;
            while (x--) b += b % 10;
            return a * b;
        };
        for (int i = 0, l, r; i < 4; i++) {
            l = 0, r = (k - i) / 4;
            for (int lm, rm, fl, fr; r - l >= 10;) {
                lm = l + (r - l + 1) / 3, rm = r - (r - l + 1) / 3;
                fl = f(4 * lm + i), fr = f(4 * rm + i);
                res = max({res, fl, fr});
                if (fl == fr) l = lm + 1, r = rm - 1;
                else if (fl < fr) l = lm + 1;
                else r = rm - 1;
            }
            for (int j = l; j <= r; j++)
                res = max(res, f(4 * j + i));
        }
    }
    cout << res << "\n";
}

int32_t main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int T;
    cin >> T;
    while (T--)
        solve();
    return 0;
}