这场感觉好卡。

A - Digit Machine

如果当前数字是 $k$,按下一次后会变成 $a_k$。求按 $3$ 次后的数字。

分析

模拟即可。

int main() {
	vector<int> v(10);
	for (auto &vi : v)
		cin >> vi;
	int x = 0;
	for (int i = 0; i < 3; i++)
		x = v[x];
	cout << x;
	return 0;
}

全部代码请看:Atcoder/ABC241/ABC241A.cpp

B - Pasta

把数组 $\{b_m\}$ 的数字映射到 $\{a_n\}$ 上,不能重复。问是否能够完全映射。

分析

mutiset<int> 模拟即可。

int main() {
	int n, m;
	cin >> n >> m;
	multiset<int> s;
	for (int i = 0; i < n; i++) {
		int t;
		cin >> t;
		s.insert(t);
	}
	for (int i = 0; i < m; i++) {
		int t;
		cin >> t;
		if (s.count(t) == 0) {
			cout << "No";
			return 0;
		}
		s.erase(s.find(t));
	}
	cout << "Yes";
	return 0;
}

全部代码请看:Atcoder/ABC241/ABC241B.cpp

C - Connect 6

给定一个地图,你可以把两个位置改为 #,问是否能够产生连续的 $6$ 个 #。横、竖、斜皆可。

分析

对于每个点,暴力搜一遍即可。

int main() {
	int n;
	cin >> n;
	vector<string> m(n);
	for (auto &mi : m) {
		cin >> mi;
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			auto sharp = [&](int x, int y) {
				int ti = i, tj = j;
				int sum = 0;
				for (int u = 0; u < 6; u++) {
					if (ti < 0 || tj < 0 || ti >= n || tj >= n) {
						return false;
					}
					sum += m[ti][tj] == '#';
					ti += x, tj += y;
				}
				return sum >= 4;
			};

			bool flag = false;
			flag = flag || sharp(1, 0) || sharp(1, 1) || sharp(0, 1) || sharp(-1, 1);
			flag = flag || sharp(-1, 0) || sharp(-1, -1) || sharp(0, -1) || sharp(1, -1);
			if (flag) {
				cout << "Yes";
				return 0;
			}
		}
	}
	cout << "No";
	return 0;
}

全部代码请看:Atcoder/ABC241/ABC241C.cpp

D - Sequence Query

给定一个空序列 $A$,和 $Q$ 个询问

  • 1 x,把 $x$ 插入 $A$。
  • 2 x k,在所有小于等于 $x$ 的数中,找出第 $k$ 大数。
  • 3 x k,在所有大于等于 $x$ 的数中,找出第 $k$ 小数。

其中 $k \leqslant 5$。

分析

我还楞了一会,发现 mutiset<ll> 好像可以直接秒。

int main() {
	int Q;
	cin >> Q;
	multiset<ll> s;
	while (Q--) {
		ll op, x, k;
		cin >> op >> x;
		if (op == 1) {
			s.insert(x);
		} else {
			cin >> k;
			auto iter = s.begin();
			bool flag = false;
			if (op == 2) {
				iter = s.upper_bound(x);
				while (iter != s.begin() && k--)
					iter--;
				flag = k > 0;
			} else {
				iter = s.lower_bound(x);
				k--;
				while (iter != s.end() && k--)
					iter++;
				flag = iter == s.end();
			}
			if (flag)
				cout << "-1\n";
			else
				cout << *iter << "\n";
		}
	}
}

全部代码请看:Atcoder/ABC241/ABC241D.cpp

E - Putting Candies

给定一个长为 $N$ 的序列 $A$,初始数字 $X = 0$。

  • 每次让 $X \gets X + A_{(X \bmod N)}$。

问 $K$ 次操作后有答案是多少。

分析

我第一想法是倍增,然后想了想存在循环节,就不写倍增了。

注意到当值为 $X$ 时,其下一个位置和增加的量仅与 $X \bmod N$ 有关,故取值最多 $n$ 种,必然存在循环。

把环判出来,首尾额外处理一下即可。

int main() {
	ll n, k;
	cin >> n >> k;
	vector<ll> v(n), vis(n);
	for (auto &vi : v)
		cin >> vi;

	auto get = [&](ll u, const ll p = 0) {
		ll ans = p, pos = p % n;
		while (u--) {
			ans += v[pos];
			pos = ans % n;
		}
		return ans - p;
	};

	ll cnt = 0, pos = 0, tsum = 0;
	while (!vis[pos]) {
		vis[pos] = cnt++;
		tsum += v[pos];
		pos = tsum % n;
	}
	ll crc = cnt - vis[pos], left = k - vis[pos];
	ll ans = 0;
	if (left < 0) {
		ans += get(k);
	} else {
		ans = get(crc, pos) * (left / crc) + get(vis[pos] + left % crc);
	}
	cout << ans;
	return 0;
}

全部代码请看:Atcoder/ABC241/ABC241E.cpp