AtCoder Beginner Contest 347

PHarr發表於2024-04-13

A - Divisible

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

#define int i64

using vi = vector<i64>;
using pii = pair<int, int>;
using piii = tuple<int, int, int>;


const int inf = 1e18;

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int n , k;
    cin >> n >> k;
    for( int i = 1 , x ; i <= n ; i ++ ){
        cin >> x;
        if( x % k == 0 ) cout << x / k << " ";
    }
    return 0;
}

B - Substring

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

#define int i64

using vi = vector<i64>;
using pii = pair<int, int>;
using piii = tuple<int, int, int>;


const int inf = 1e18;

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    string s;
    cin >> s;
    set<string> cnt;
    for (int i = 0; i < s.size(); i++)
        for (int j = 1; i + j <= s.size(); j++)
            cnt.insert(s.substr(i, j));
    cout << cnt.size() << "\n";
    return 0;
}

C - Ideal Holidays

首先要做一個取模,然後列舉取模後所有的點做起點,判斷能不能把所有的工作都安排在假期。

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

#define int i64

using vi = vector<i64>;
using pii = pair<int, int>;
using piii = tuple<int, int, int>;


const int inf = 1e18;

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int n, a, b;
    cin >> n >> a >> b;
    b += a;
    vi d(n);
    for (auto &i: d) {
        cin >> i, i = (i - 1) % b;
    }
    set<int> c;
    for (auto i: d)
        c.insert(i);
    if( c.size() == 1 ){
        cout << "Yes\n";
        return 0;
        
    }
    while (true) {
        int x = *c.begin();
        if (x >= b) break;
            c.erase(c.begin());
        if (*c.rbegin() < x + a) {
            cout << "Yes\n";
            return 0;
        }
        c.insert(x + b);
    }
    cout << "No\n";
    return 0;
}

D - Popcount and XOR

首先我們統計出\(popcpunt(C) = t\)。然後我們\(X,Y\)異或能得到的數的一的數量的範圍是\([abs(X-Y) , X + Y]\),判斷\(t\)是否在這個範圍內。

然後我們設抵消的一的個數有\(x\)個,則題目可知$a + b - 2*x = t \(,則\)a + b + t = 2t - 2 * x \(,所以\)a+b+t\(一定是偶數,並且\)\frac{a + b + 2 }{ 2} = t - x $,根據題目可知\(0\le \frac {a+b+t}{2} \le 60\)恆成立。

然後我們算出\(x\)的值,開始一位位的遍歷\(C\)即可,每一位的值如果是0,就可以給兩個兩個數這一位賦值為 1,如果是 1 就可以跟任意一個數賦值為 1.

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

#define int i64

using vi = vector<i64>;
using pii = pair<int, int>;
using piii = tuple<int, int, int>;
using node = bitset<60>;

const int N = (1ll << 60);

i32 main() {
    int a, b, c;
    cin >> a >> b >> c;
    node C(c);
    int t = C.count();
    if (a + b < t or t < abs(a - b) or (a + b + t) % 2 != 0 or (a + b + t) / 2 > 60) {
        cout << "-1\n";
        return 0;
    }
    t = (a + b - t) / 2, a -= t, b -= t;
    int x = 0, y = 0;
    for (int i = 59; i >= 0; i--) {
        x <<= 1, y <<= 1;
        if (C[i]) {
            if (a > 0) x |= 1, a--;
            else if (b > 0) y |= 1, b--;
        } else {
            if (t > 0) x |= 1, y |= 1, t--;
        }
    }
    cout << x << " " << y << "\n";

    return 0;
}

E - Set Add Query

set模擬出這個集合,並把第\(i\)次操作後set的大小記為\(sum[i]\),並且統計出每個數字操作的位置。

對於每個數字,實際上就是奇數次操作到偶數次操作中間的部分,這一部分可以用字首和快速求出來。

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

#define int i64

using vi = vector<i64>;
using pii = pair<int, int>;
using piii = tuple<int, int, int>;

const int inf = 1e18;

i32 main() {
    int n, q;
    cin >> n >> q;
    vector<vi> op(n + 1);
    vi sum(q + 1);
    set<int> s;
    for (int i = 1, x; i <= q; i++) {
        cin >> x;
        if (s.count(x)) s.erase(x);
        else s.insert(x);
        sum[i] = sum[i - 1] + s.size();
        op[x].push_back(i);
    }
    for (auto &it: op)
        if (it.size() % 2 == 1) it.push_back(q + 1);
    for (int i = 1, ans; i <= n; i++) {
        ans = 0;
        for (int j = 1; j < op[i].size(); j += 2)
            ans += sum[op[i][j] - 1] - sum[op[i][j - 1] - 1];
        cout << ans << " ";
    }
    return 0;
}