Featured image of post Codeforces Round #1008(Div.2)

Codeforces Round #1008(Div.2)

B

题目大意:迷宫中有 $n$ 个单元格,其中单元格 $i$($1 \leq i \leq n$)距离出口有 $n - i$ 公里。特别地,单元格 $n$ 就是出口。注意每个单元格仅与出口相连,无法从其他任何单元格直接到达。每个单元格最初恰好困住一个人。你希望通过在每个单元格 $i$($1 \leq i \leq n$)安装传送器来帮助所有人尽可能接近出口,该传送器会将单元格 $i$ 中的人传送到另一个单元格 $a_i$。迷宫主人发现了你的行为。她觉得有趣,但要求你满足以下条件: - 每个人都必须恰好使用传送器 $k$ 次。

数据范围:$1 \le t \le 10^4$,$2 \leq n \leq 2 \cdot 10^5$,$1 \leq k \leq 10^9$,$\sum n \le 2 \cdot 10^5$。

思路:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
void solve() {
    int n, k;
    cin >> n >> k;
    vi res(n);
    if (k % 2 == 1) {
        rep(i, 0, n - 2) res[i] = n;
        res[n - 1] = n - 1;
    } else {
        res[n - 2] = n;
        rep(i, 0, n - 1) {
            if (i == n - 2) continue;
            res[i] = n - 1;
        }
    }
    rep(i, 0, n - 1) cout << res[i] << ' ';
    cout << endl;
    return;
}

C

题目大意:你和你的团队不懈努力,最终得到了一个满足以下性质的正整数序列 $a_1, a_2, \ldots, a_{2n+1}$: - 对于所有 $1 \le i \le 2n + 1$,有 $1 \le a_i \le 10^{18}$。- $a_1, a_2, \ldots, a_{2n+1}$ 两两互不相同。- $a_1 = a_2 - a_3 + a_4 - a_5 + \ldots + a_{2n} - a_{2n+1}$。然而,与你合作的人为了抢先发表这个序列而背叛了你。

数据范围:$1 \le t \le 10^4$,$1 \leq n \leq 2 \cdot 10^5$,$1 \leq b_i \leq 10^9$,$\sum n \le 2 \cdot 10^5$。

思路:

 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;
    vl a(2 * n);
    rep(i, 0, 2 * n - 1) cin >> a[i];
    ranges::sort(a);
    ll tem1 = 0;
    ll tem2 = 0;
    rep(i, 0, n - 2) tem2 += 1LL * a[i];
    rep(i, n - 1, 2 * n - 1) tem1 += 1LL * a[i];
    ll tem = tem1 - tem2;
    vl b(2 * n + 1);
    for (int i = 0; i <= 2 * n; i += 2) b[i] = a[2 * n - 1 - i / 2];
    for (int i = 1; i < 2 * n - 1; i += 2) b[i] = a[(i - 1) / 2];
    b[2 * n - 1] = tem;
    for (ll p : b) cout << p << ' ';
    cout << endl;
    return;
}

D

题目大意:考虑以下游戏。 游戏中每个关卡包含 $n$ 对门。每对门包含一个左门和一个右门。每个门执行以下两种操作之一: - 加法操作 (+ $a$):将该通道的人数增加固定值 $a$。- 乘法操作 (× $a$):将该通道当前人数乘以整数 $a$。这意味着该通道人数将增加 $(a - 1)$ 倍当前值。每个操作产生的新增人员可以分配到任意通道。但已存在于某个通道的人员不可转移到另一个通道。初始时,每个通道各有 $1$ 人。

数据范围:$1 \leq t \leq 10^4$,$1 \leq n \le 30$,$1 \le a \le 1000$,$2 \le a \le 3$。

思路:

 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
void solve() {
    int n;
    cin >> n;
    vector<pll> ma(n);
    vector<pair<char, char>> op(n);
    rep(i, 0, n - 1) { cin >> op[i].first >> ma[i].first >> op[i].second >> ma[i].second; }
    vector<pll> suf(n + 1);
    suf[n].first = suf[n].second = 1;
    frep(i, n - 1, 0) {
        suf[i] = suf[i + 1];
        if (op[i].first == 'x') suf[i].first += max(suf[i + 1].first, suf[i + 1].second) * (ma[i].first - 1);
        if (op[i].second == 'x') suf[i].second += max(suf[i + 1].first, suf[i + 1].second) * (ma[i].second - 1);
    }
    ll l = 1, r = 1;
    rep(i, 0, n - 1) {
        ll tem = 0;
        if (op[i].first == '+')
            tem += ma[i].first;
        else
            tem += (ma[i].first - 1) * l;
        if (op[i].second == '+')
            tem += ma[i].second;
        else
            tem += (ma[i].second - 1) * r;
        if (suf[i + 1].first >= suf[i + 1].second)
            l += tem;
        else
            r += tem;
    }
    cout << l + r << endl;
    return;
}

E

题目大意:这是一道交互题。存在两个隐藏的非负整数 $x$ 和 $y$($0 \leq x, y < 2^{30}$)。你最多可以提出 2 次以下形式的询问: - 选择一个非负整数 $n$($0 \leq n < 2^{30}$)。

数据范围:$1 \le t \le 10^4$。

思路:

 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
const int tem1 = 715827882;
const int tem2 = 357913941;
ll ask(ll l) {
    cout << l << '\n';
    cout.flush();
    ll op;
    cin >> op;
    return op;
}
ll report() {
    cout << "! " << '\n';
    cout.flush();
    ll op;
    cin >> op;
    return op;
}
void report2(ll x) {
    cout << x << '\n';
    cout.flush();
}
void solve() {
    ll tem3 = ask(tem1);
    tem3 -= 2 * tem1;
    ll tem4 = ask(tem2);
    tem4 -= 2 * tem2;
    ll m = report();
    ll x = 0, y = 0;
    for (int i = 0; i < 30; i += 2) {
        if ((tem3 >> i) & 1)
            x |= (1LL << i);
        else if ((tem3 >> (i + 1)) & 1)
            x |= (1LL << i), y |= (1LL << i);
    }
    for (int i = 1; i < 30; i += 2) {
        if ((tem4 >> i) & 1)
            x |= (1LL << i);
        else if ((tem4 >> (i + 1)) & 1)
            x |= (1LL << i), y |= (1LL << i);
    }
    report2((x | m) + (y | m));
    return;
}

F

题目大意:给定二进制字符串 $v$,其分数由某个切分点左右两段的函数值乘积取最大得到,其中 $F(v,l,r)$ 与区间长度和 $0$ 的个数有关。需要按题意处理字符串与询问,计算对应分数。

数据范围:$1 \le t \le 10^4$,$1 \leq n \leq 2 \cdot 10^5$,$1 \leq q \leq 2 \cdot 10^5$,$1 \leq i \leq n$,$\sum n \le 2 \cdot 10^5$,$\sum q \le 2 \cdot 10^5$。

思路:

 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
const ll MOD = 998244353;
ll mul(ll x, ll y) { return x * y % MOD; }
ll qpow(ll x, ll y) {
    ll z = 1;
    while (y > 0) {
        if (y & 1) z = mul(z, x);
        x = mul(x, x);
        y >>= 1;
    }
    return z;
}  // 求x**y%MOD

// 注意:当MOD为质数时, (x/y)%MOD=(x*(y**(MOD-2)))%MOD,即y在模MOD意义下的逆元为b^{-1} \equiv b^{p-2} mod p

void solve() {
    int n, q, x;
    cin >> n >> q;
    string s;
    cin >> s;
    ll tot = 0;
    rep(i, 0, n - 1) tot += (s[i] == '1' ? 1 : -1);
    rep(i, 0, q - 1) {
        cin >> x;
        x--;
        tot -= (s[x] == '1' ? 2 : -2);
        s[x] = (s[x] == '1' ? '0' : '1');
        cout << (n <= 4 ? qpow((1 << (4 - n)), MOD - 2) * (tot * tot % MOD + n - 2 + MOD) % MOD
                        : qpow(2, n - 4) * (tot * tot % MOD + n - 2 + MOD) % MOD)
             << endl;
    }
    return;
}