这场属实阴间。

A. Acacius and String

替换字符串 $s$ 中的 ?,使得出现且仅出现一次 abacaba

分析

本题较为难写,因为很难判断恰好出现了一次。但是数据规模很小,可以采用非常暴力的写法。

一种想法是,枚举每个出现 abacaba 的位置 $i$,把当前 $s[i, i + 6]$ 中的 ? 设为给定串,这样就得到了字符串 $t$。

然后判断字符串 $t$ 中只出现了一次 abacaba,可以通过 substr 枚举所有长为 $6$ 的子串。

string what = "abacaba";
int N = what.length();

void solve() {
	int n;
	string s;
	cin >> n >> s;
	for (int i = 0; i <= n - N; i++) {
		string tmp = s;
		for (int j = 0; j < N; j++) {
			if (tmp[i + j] == '?') {
				tmp[i + j] = what[j];
			}
		}
		for (int j = 0; j < tmp.length(); j++) {
			if (tmp[j] == '?')
				tmp[j] = 'z';
		}
		int cnt = 0;
		for (int j = 0; j <= tmp.length() - N; j++) {
			if (tmp.substr(j, N) == what)
				cnt++;
		}
		if (cnt == 1) {
			cout << "Yes\n" << tmp << "\n";
			return;
		}
	}
	cout << "No\n";
}

全部代码请看:Codeforces/CF1379/CF1379A.cpp

B. Dubious Cyrpto

给定 $l,r,m$,找到正整数 $a,b,c,n$ 满足 $m = an + b - c$,且 $l \leqslant a,b,c \leqslant r$。

分析

反解 $n$ 得到

$$ \frac{m - (b - c)}{a} = n $$

我们可以把 $b - c$ 当作一个整体。注意到 $n$ 是正整数,说明 $m - (b - c)$ 必须要能够整除 $a$,而且 $a$ 的范围不是很大,因此我们可以枚举 $a$。

再注意到 $b-c$ 的范围是 $[l-r,r-l]$,即判断 $m \bmod a$ 是否在这个范围内。

void solve() {
	ll l, r, m;
	cin >> l >> r >> m;
	for (ll a = l; a <= r; a++) {
		int b_c = (m + r - l) % a - (r - l);
		if (b_c > r - l)
			continue;
		if (b_c < 0)
			cout << a << " " << (r + b_c) << " " << r << "\n";
		else
			cout << a << " " << (l + b_c) << " " << l << "\n";
		break;
	}
}

全部代码请看:Codeforces/CF1379/CF1379B.cpp

C. Choosing flowers

对于 $n$ 种花,如果其中第 $i$ 种选择了 $x_i > 0$ 朵,那么其贡献是

$$ a_i + (x_i - 1) b_i $$

怎样选择才能使整体的贡献最大。

分析

很精妙的贪心。先假设选择的花的集合 $S \subset \mathbb{N}_{\leqslant n}$,每种先选 $1$ 朵,接下来考虑剩下的数量如何分配。必然的,应该全部分配给 $S$ 中最大的 $b_i$。

换种角度考虑,答案可能是全部只选了 $1$ 朵,或者必然只有一种多于 $1$ 朵。我们可以考虑枚举第 $i$ 朵花多于 $1$ 朵。

再注意到,当第 $j$ 种花满足 $a_j > b_i$ 时,应该选择一朵 $a_j$。

全部的 $a_j > b_i$ 可以通过二分 + 前缀和得到,需注意分类讨论前缀和是否包含了 $a_i$。

void solve() {
	int n, m;
	cin >> n >> m;
	vector<pii> v(m + 1);
	for (int i = 1; i <= m; i++) {
		cin >> v[i].x >> v[i].y;
	}
	sort(v.begin() + 1, v.end());
	vector<ll> sum(m + 1);
	for (int i = 1; i <= m; i++) {
		sum[i] = sum[i - 1] + v[i].x;
	}
	ll ans = 0;
	for (int i = 1; i <= m; i++) {
		int pos = upper(1, m, [&](int M) {
			return v[M].x > v[i].y;
		});
		int num = m - pos + 1;
		if (num <= n) {
			ll tans = sum[m] - sum[pos - 1] + (n - num) * v[i].y;
			if (pos > i) {
				tans += v[i].x - v[i].y;
			}
			ans = max(ans, tans);
		} else {
			ans = max(ans, sum[m] - sum[max(0, m - n)]);
		}
	}
	cout << ans << "\n";
}

全部代码请看:Codeforces/CF1379/CF1379C.cpp