Codeforces Round 917 (Div. 2)更新中...

A.Least Product(思维)

题意:

给出一个数组 a 1 , a 2 , . . . , a n a_1, a_2, ..., a_n a1,a2,...,an,你可以进行若干次以下操作:

  • 选择数组中的一个元素 a i a_i ai,将这个数字修改为 0 ∼ a i 0 \sim a_i 0ai之间的任意数字。

问,最少需要多少次操作可以使得 ∏ i = 1 n a i \prod\limits_{i = 1}^{n}a_i i=1nai的结果最小,并输出对应的操作。

分析:

可以将问题分成两种情况:

  • 存在 a i = 0 a_i = 0 ai=0或负数的出现次数为奇数,此时无论进行任何操作都无法使结果变得更小,输出0

  • 其他情况,由于数字只能被修改到 0 ∼ a i 0 \sim a_i 0ai之间,那么正负数是无法互相转换的,因此,当结果为正数时,任选一个 a i a_i ai,将其修改为 0 0 0,就能获得最小的结果

代码:

#include

using namespace std;
typedef long long LL;
const int MAXN = 3e5 + 5e2;


void solve() {
    int n;
    cin >> n;
    int zero = 0, sign = 0;
    for (int i = 1; i <= n; i++) {
        int a;
        cin >> a;
        if (a == 0) {
            zero = 1;
        } else if (a < 0) {
            sign++;
        }
    }
    if (zero || sign % 2 == 1) cout << 0 << endl;
    else {
        cout << 1 << endl;
        cout << "1 0" << endl;
    }
}

int main() {
    int Case;
    cin >> Case;
    while (Case--) {
        solve();
    }
    return 0;
}

B.Erase First or Second Letter(思维)

题意:

给出一个长度为 n n n的字符串 s s s,你可以进行若干次以下操作:

  • 移除第一个字符

  • 移除第二个字符

问:经过若干次操作后,可以获得多少种不同的非空字符串?

分析:

将字符串划分为前后两部分,枚举两部分的分界点,每次枚举完分界点后,将后半部分视为不进行修改的部分,仅会对前半部分进行操作,那么由于每次枚举的后半部分均不同,为了保证方案的独立性,前半部分仅保留一个字符,那么此时的方案数就是前半部分中包含的不同字母的数量。

使用计数数组或set动态记录不同字符数量,每次枚举分界点后更新前半部分字符种类并记录到答案中即可。

代码:

#include

using namespace std;
typedef long long LL;
const int MAXN = 3e5 + 5e2;

int vis[30];

void solve() {
    memset(vis, 0, sizeof (vis));
    int n;
    string s;
    cin >> n >> s;
    int cnt = 0, ans = 0;
    for (int i = 0; i < n; i++) {
        vis[s[i] - 'a']++;
        if (vis[s[i] - 'a'] == 1) cnt++;
        ans += cnt;
    }
    cout << ans << endl;
}

int main() {
    int Case;
    cin >> Case;
    while (Case--) {
        solve();
    }
    return 0;
}

C.Watering an Array(枚举)

题意:

给出一个长度为 n n n的数组 a a a,你将在接下来的 d d d天里每天选择执行以下两个操作之一:

  • 给所有的 a 1 , a 2 , . . . , a b i a_1, a_2, ..., a_{b_i} a1,a2,...,abi加上一,其中 b i b_i bi为题目给出的第 i i i天的操作数。

  • 数组 a a a a i = i a_i = i ai=i的数量就是你本轮获得的得分,然后将 a a a数组所有元素修改为 0 0 0

问:最多可以获得多少得分?

Tips:由于天数较多,因此 b b b数组采用 b = [ v 1 , v 2 , . . . , v k , v 1 , v 2 , . . . , v k , . . . ] b = [v_1, v_2, ..., v_k, v_1, v_2, ..., v_k, ...] b=[v1,v2,...,vk,v1,v2,...,vk,...]的形式给出。

分析:

如果数组 a a a开始全部为 0 0 0,那么最优策略就是操作 1 , 2 1,2 1,2轮流进行,可以获得 ⌊ d 2 ⌋ \lfloor\frac{d}{2}\rfloor 2d点得分(注意:开始时若 a 1 ≥ 1 a_1 \ge 1 a11,则需要使用一次操作 2 2 2 a 1 a_1 a1修改为 0 0 0,此时得分为 ( ⌊ d − 1 2 ⌋ + 开始时数组元素可以产生的得分 (\lfloor\frac{d - 1}{2}\rfloor + \text{开始时数组元素可以产生的得分} (⌊2d1+开始时数组元素可以产生的得分)。

而由于初始的数组是包含初始数字的,且长度为 n n n的数组最多可以产生 n n n点得分,因此,只需要在 2 × n 2 \times n 2×n的操作次数内均有可能超过循环操作获取的 n n n点固定得分。

枚举第一次进行操作 2 2 2前会进行多少次操作 1 1 1,每次遍历数组统计得分,剩余的操作次数使用最优策略进行。记录过程中最大的得分即可。

坑点

既然获取的长度为 n n n的数字最高可以产生 n n n点得分,那么只枚举 n n n次操作是否就够了?

反例:

原数组为 2 , 1 , 2 , . . . , n − 1 2, 1, 2, ..., n - 1 2,1,2,...,n1,给出的 b b b数组为 [ 1 , 1 , . . . , 1 , n ] [1, 1, ..., 1, n] [1,1,...,1,n],其中 b i = n b_i = n bi=n前有 ( 2 × n ) − 4 (2 \times n) - 4 (2×n)4个1,此时 d = 2 × n d = 2 \times n d=2×n

可以发现,枚举 0 ∼ n 0 \sim n 0n次操作 1 1 1,均无法产生额外得分,此时获得的最高总分为 ⌊ d − 1 2 ⌋ = n − 1 \lfloor \frac{d - 1}{2} \rfloor = n - 1 2d1=n1,而依次使用 ( 2 × n ) − 3 (2 \times n) - 3 (2×n)3次操作 1 1 1,再进行操作 2 2 2,可以获得 n − 1 n - 1 n1点得分,此时还剩下两次操作,还可以继续一次最优策略,最后得分为 n n n

代码:

#include

using namespace std;
typedef long long LL;
const int MAXN = 3e5 + 5e2;

LL a[MAXN], b[MAXN];

void solve() {
    LL n, k, d;
    cin >> n >> k >> d;
    LL ans = 0;
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 0; i < k; i++) cin >> b[i];
    for (int i = 0; i <= 2 * n && i < d; i++) {
        LL cnt = 0;
        for (int j = 1; j <= n; j++) if (a[j] == j) cnt++;
        ans = max(ans, cnt + (d - i - 1) / 2);
        for (int j = 1; j <= b[i % k]; j++) {
            if (a[j] == j) cnt--;
            a[j]++;
            if (a[j] == j) cnt++;
        }
    }
    cout << ans << endl;
}

int main() {
    int Case;
    cin >> Case;
    while (Case--) {
        solve();
    }
    return 0;
}

学习交流

以下为学习交流QQ群,群号: 546235402,每周题解完成后都会转发到群中,大家可以加群一起交流做题思路,分享做题技巧,欢迎大家的加入。

Codeforces Round 917 (Div. 2)更新中..._第1张图片

你可能感兴趣的:(codeforces题解,算法,OI,codeforces)