1. 程式人生 > >Codeforces Round #508 (Div. 2)

Codeforces Round #508 (Div. 2)

A. Equality

因為是子序列,所以只要判斷前 kk 個字母最多組成多少個子序列就行了

#include <iostream>
#include <climits>
#include <algorithm>

const int MAXN = 1e5 + 2;

std::string str;
int n, k, ans = INT_MAX;
int cnt[MAXN];

int main()
{
    std::ios_base::sync_with_stdio(0);
    std::cin >> n >> k >>
str; for (int i = 0; i < n; i++) { cnt[str[i] - 'A']++; } for (int i = 0; i < k; i++) { ans = std::min(ans, cnt[i]); } std::cout << ans * k << std::endl; return 0; }

B. Non-Coprime Partition

根據求和公式,前 n1n-1 項和為 (n1)n2\frac{(n-1)n}{2}

n ,而最後一項正是 nn ,兩者的 gcdgcd 就是 nn ,然後再特判一下 n=1n=1n=2n=2 的情況就行了

#include <bits/stdc++.h>

using namespace std;

int n;

int main()
{
	scanf("%d", &n);
	if (n == 1) puts("No");
	else if (n == 2) puts("No");
	else {
		puts("Yes");
		printf("%d ", n - 1);
		for (int i = 1; i < n;
i++) { printf("%d ", i); } printf("\n1 %d\n", n); } return 0; }

C. Gambling

根據題意,AABB 每次都要移除對手的一個數字或者拿走自己的一個數字,容易發現 AABB 每次都將移除或拿走當前最大的數字,所以直接模擬即可

#include <cstdio>
#include <algorithm>

const int MAXN = 100000 + 5;

int n;
long long ans;
int a[MAXN], b[MAXN];

int main()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
	for (int i = 1; i <= n; i++) scanf("%d", &b[i]);
	std::sort(a + 1, a + 1 + n);
	std::sort(b + 1, b + 1 + n);

	int na = n, nb = n;
	char turn = 'a';

	while (na > 0 && nb > 0) {
		if (turn == 'a') {
			if (a[na] > b[nb]) {
				ans += a[na];
				na--;
			}
			else nb--;

			turn = 'b';
		}
		else {
			if (b[nb] > a[na]) {
				ans -= b[nb];
				nb--;
			}
			else na--;

			turn = 'a';
		}
	}

	if (na > 0) {
		if (turn == 'a') {
			for (int i = na; i >= 1; i -= 2) {
				ans += a[i];
			}
		}
		else {
			for (int i = na - 1; i >= 1; i -= 2) {
				ans += a[i];
			}
		}
	}

	if (nb > 0) {
		if (turn == 'a') {
			for (int i = nb - 1; i >= 1; i -= 2) {
				ans -= b[i];
			}
		}
		else {
			for (int i = nb; i >= 1; i -= 2) {
				ans -= b[i];
			}
		}
	}

	printf("%lld\n", ans);
	return 0;
}

D. Slime

設全部數字絕對值之和為 sumsum。 當全部都是正數的時候,讓一個數 aa 不斷減去他旁邊的數到只剩 22 個數字,然後再用剩的那個數字 bb 減去 aa ,這樣每個數相當於都加到了 bb 中,唯獨 aa 不但沒加還減去了,所以最後答案為 sum2asum-2a 。 當全部都是負數的時候和上面同理,最後答案為 sum2asum-|2a| 當有正有負的時候讓負數減去旁邊的正數直到只剩一個正數,然後那個正數再減掉所有的負數就好,所以答案為 sumsum。 所以要讓答案最大就是讓 2a|2a| 最小。

#include <cstdio>
#include <algorithm>
#include <climits>

int n, max = INT_MIN, min = INT_MAX;
long long ans;

int main()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		int tmp;
		scanf("%d", &tmp);
		max = std::max(max, tmp);
		min = std::min(min, tmp);
		ans += abs(tmp);
	}

	if (n == 1) {
		printf("%d\n", max);
		return 0;
	}
	else if (n == 2) {
		printf("%d\n", abs(max - min));
		return 0;
	}

	if (max < 0) {
		printf("%lld\n", ans - 2 * abs(max));
	}
	else if (min > 0) {
		printf("%lld\n", ans - 2 * abs(min));
	}
	else printf("%lld", ans);
	return 0;
}