A. Doors and Keys

RGB 三种门,和 rgb 三种钥匙。如果门先于其对应的钥匙出现,则会卡关。判断字符串是否意味着卡关。

分析

枚举即可。

int main() {
	int T;
	cin >> T;
	while (T--) {
		string s;
		cin >> s;
		vector<int> flag(26);
		bool ans = true;
		for (char si : s) {
			if (si >= 'a') {
				flag[si - 'a'] = true;
			} else {
				if (!flag[si - 'A']) {
					ans = false;
				}
			}
		}
		if (ans)
			cout << "YES\n";
		else
			cout << "NO\n";
	}
	return 0;
}

B. Anti-Fibonacci Permutation

如果长 $n$ 的排列 $p$ 是反斐波那契排列,即对所有元素

$$ p_{i-2} + p_{i-1} \neq p_i $$

都成立。构造出 $n$ 个长为 $n$ 的反斐波那契排列。

分析

我的第一想法是爆搜,后来想到 $1+2=3$ 会使得开始会 T,想到交换 $2,3$ 应该就没问题了。

int main() {
	int T;
	cin >> T;
	while (T--) {
		int n;
		cin >> n;
		vector<int> v(n);
		for (int i = 0; i < n; i++) {
			v[i] = i + 1;
		}
		swap(v[1], v[2]);
		auto judge = [&]() {
			for (int i = 2; i < n; i++) {
				if (v[i] == v[i - 1] + v[i - 2])
					return false;
			}
			return true;
		};

		int cnt = 0;
		do {
			if (judge()) {
				cnt++;
				for (auto vi : v)
					cout << vi << " ";
				cout << "\n";
				if (cnt == n)
					break;
			}
		} while (next_permutation(v.begin(), v.end()));
	}
	return 0;
}

看了别人的代码,发现构造可以更加简单。

int main() {
	int T;
	cin >> T;
	while (T--) {
		int n;
		cin >> n;
		vector<int> v(n + 1);
		for (int i = n; i >= 1; i--) {
			v[i] = n - i + 1;
		}
		for (int i = n; i >= 1; i--) {
			for (int j = 1; j <= n; j++)
				cout << v[j] << " \n"[j == n];
			swap(v[i - 1], v[i]);
		}
	}
	return 0;
}

C. Increase Subarray Sums

给定一个长为 $n$ 的序列 $\{a_i\}$,每次操作可以选择一个位置加上 $x$。记 $f(k)$ 为经过 $k$ 次操作后,最大的连续子序列和。

分析

第一想法是贪心,但是 $f(n)$ 的选择可能和 $f(n-1)$ 完全不同。

注意到我们之所以不能延后加 $x$,是因为答案长度不一定长于 $k$。只需把不同长度的答案分开即可,这可以通过 DP 得到。

int main() {
	int T;
	cin >> T;
	while (T--) {
		int n, x;
		cin >> n >> x;
		vector<int> a(n);
		for (auto &ai : a)
			cin >> ai;
		vector<int> dp(n + 1, -1E9);
		dp[0] = 0;
		for (int i = 0; i < n; i++) {
			int sum = 0;
			for (int j = i; j < n; j++) {
				sum += a[j];
				dp[j - i + 1] = max(sum, dp[j - i + 1]);
			}
		}
		for (int k = 0; k <= n; k++) {
			int ans = 0;
			for (int i = 0; i <= n; i++)
				ans = max(ans, dp[i] + min(i, k) * x);
			cout << ans << " \n"[k == n];
		}
	}
	return 0;
}