专栏文章

题解:CF2008G Sakurako's Task

CF2008G题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@min0y7kg
此快照首次捕获于
2025/12/01 18:46
3 个月前
此快照最后确认于
2025/12/01 18:46
3 个月前
查看原文

CF2008G

我们会发现,因为需要求的是 mex,所以在所有数都不同的情况下,每个数尽可能小是最优的。
由于操作是 ai=aiaj,ai=ai+aja_i = a_i - a_j, a_i = a_i + a_j 这两种,所以我们一定可以凑出 {0,gcd(a1,,an),,(n1)gcd(a1,,an)}\{0, \gcd(a_1, \dots, a_n), \dots, (n - 1) \cdot gcd(a_1, \dots, a_n)\} 这个序列。
感性理解一下为什么可以取到 00
就是首先我们是肯定可以取到 gcd\gcd 的,然后,我们通过将 gcd\gcd 和另外两个数分别进行操作,就得到了三个 gcd\gcd
然后对于这三个 gcd\gcd,我们对于其中两个做一次操作就可以得到 0,gcd,2×gcd0, \gcd, 2 \times \gcd
因此,我们可以枚举 mexkmex_k 具体是处于哪一个区间 [igcd(a1,,an),(i+1)gcd(a1,,an)1][i \cdot \gcd(a_1, \dots, a_n), (i + 1) \cdot \gcd(a_1, \dots, a_n) - 1],然后输出即可。
CPP
#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;

int T, n, k, a[N];

int gcd(int x, int y) {
    return y ? gcd(y, x % y) : x;
}

void Solve() {
    cin >> n >> k;
    for (int i = 1; i <= n; i++) cin >> a[i];
    if (n == 1) {
        cout << k - (k <= a[1]) << '\n';
        return ;
    }
    int tp = 0;
    for (int i = 1; i <= n; i++) tp = gcd(tp, a[i]);
    for (int i = 0; i < n; i++) {
        // i * tp + 1 ~ (i + 1) * tp - 1
        if (k <= tp - 1) {
            cout << i * tp + k << '\n';
            return ;
        }
        if (i < n - 1) k -= tp - 1;
    }
    cout << (n - 1) * tp + k << '\n';
}

int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    cin >> T;
    while (T--) Solve();
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...