AtCoder Regular Contest 解题报告

好久没写 At 题解了,而且从来没写过 ARC 的题解,今天就来写一发。

这场是我有史以来表现分最高的一场,唯一可惜的就是考场上没时间写 E 了,不然差不多能进前 100。

A - Three Integers

题目链接

题意简述

给你三个数 A,B,C[0,1018]
你可以做以下两种操作:

  • 选其中两个数,让它们减去 1
  • 让全部三个数减去 1

问最少几步可以让这三个数都变成 0

解体思路

贪心,尽可能多地用操作 2
由于操作顺序无关紧要,我们先做完所有的操作 2
接下来只用操作 1,容易发现当且仅当 A+B+C0(mod2) 并且 A,B,C 中较小的两个数之和大于等于最大的数时,只用操作 1 有解。
然后嗯做就可以了,懒得再写了,具体看代码吧。

参考代码

#include <vector>
#include <iostream>
#include <algorithm>

using i64 = long long;
using vint = std::vector<int>;
using PII = std::pair<int, int>;

int main(void)
{
	//Think twice, code once.
	std::ios::sync_with_stdio(false);
	i64 a[3];
	std::cin >> a[0] >> a[1] >> a[2];
	i64 x = a[0] + a[1] + a[2];
	std::sort(a, a + 3);
	i64 res = 0;
	if (x & 1) {
		++res;
		for (int i = 0; i < 3; ++i)
			--a[i];
	}
	if (a[0] < 0) {
		puts("-1");
		return 0;
	}
	i64 k = (a[0] + a[1] - a[2]);
	if (k < 0) {
		puts("-1");
		return 0;
	}
	k = k / 2 * 2;
	res += k;
	for (int i = 0; i < 3; ++i)
		a[i] -= k;
	res += (a[0] + a[1] + a[2]) / 2;
	std::cout << res << '\n';
	return 0;
}

B - Counting Grids

题目链接

题意简述

给定一个 n[1,500],你要把 1n2 填入 大小为 n×n 的方阵中,满足对于任意一个格子,至少满足以下两个条件之一:

  • 不是它所在列的最小值。
  • 不是它所在行的最大值。

问有多少种方案,对 998244353 取模。

解体思路

明显很难直接求,考虑相反的情况:
存在一个格子,它是所在列的最小值,也是所在行的最大值。
反证法容易证明这种格子不可能同时存在两个,那我们直接枚举这个格子的值,设其为 x,它的位置有 n2 种,它所在列只能有比他大的值,所以只有 (x1n1)×(n1)! 种可能,同列它所在列只有 (nxn1)×(n1)! 种可能,其余数可以随意排列,有 (n22n+1)! 种可能。综上,相反情况的方案数就是

x=1n2n2×(x1n1)×(n1)!×(nxn1)×(n1)!×(n22n+1)!

(n2)! 减去上述式子即为答案。

参考代码

#include <vector>
#include <iostream>
#include <algorithm>

using i64 = long long;
using vint = std::vector<int>;
using PII = std::pair<int, int>;
const int N = 500 * 500 + 10, mod = 998244353;
inline int Mod(int x) { return x >= mod ? x - mod : x; }

struct ModInt
{
	int val;
	ModInt(void) { val = 0; }
	ModInt(int x) { val = x; }
	ModInt operator+(const ModInt &other) const
	{ return Mod(val + other.val); }
	ModInt operator-(const ModInt &other) const
	{ return Mod(val + mod - other.val); }
	ModInt operator*(const ModInt &other) const
	{ return 1ll * val * other.val % mod; }
};

ModInt fac[N], inv[N];
inline ModInt qpow(ModInt base, int k)
{
	ModInt res = 1;
	while (k) {
		if (k & 1) res = res * base;
		k >>= 1;
		base = base * base;
	}
	return res;
}
inline ModInt getInv(ModInt x) { return qpow(x, mod - 2); }
inline ModInt C(int n, int m)
{
	if (n < m || n < 0 || m < 0) return 0;
	return fac[n] * inv[m] * inv[n - m];
}

int main(void)
{
	//Think twice, code once.
	std::ios::sync_with_stdio(false);
	fac[0] = 1;
	for (int i = 1; i < N; ++i)
		fac[i] = fac[i - 1] * i;
	inv[N - 1] = getInv(fac[N - 1]);
	for (int i = N - 2; i >= 0; --i)
		inv[i] = inv[i + 1] * (i + 1);

	int n; std::cin >> n;
	ModInt res;
	for (int i = 1; i <= n * n; ++i) {
		ModInt o = n * n;
		o = o * C(i - 1, n - 1) * fac[n - 1];
		o = o * C(n * n - i, n - 1) * fac[n - 1];
		o = o * fac[n * n - (n + n - 1)];
		res = res + o;
	}
	std::cout << (fac[n * n] - res).val << '\n';
	return 0;
}

C - Piles of Pebbles

题目链接

题意简述

n 堆石子,第 i 堆包含 Ai 个石子。
Takahashi 和 Aoki 将会进行一场游戏,规则如下:

  • 两人轮流行动,Takahashi 先走,第一个无法行动的人失败。
  • 轮到 Takahashi 时,Takahashi 选择至少一堆包含大于等于 X 个石子的石子堆,把它们都移去 X 个石子。
  • 轮到 Aoki 时,Aoki 选择至少一堆包含大于等于 Y 个石子的石子堆,把它们都移去 Y 个石子。

问先手是否必胜。

解体思路

参考代码

D - Three Integers

题目链接

题意简述

解体思路

参考代码

E - Three Integers

题目链接

题意简述

解体思路

参考代码

F - Counting Subsets

没看,不会

posted @   LroseC  阅读(122)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示