2026 年 ACM 暑假集训
2026 年 ACM 暑假集训
2026 牛客暑期多校训练营 1
F. Permutation Generation
给定 \(n \in \mathbb{N}^*\),记 \(N = \mathbb{N} \cap [0, n)\)。 对于 \(N\) 的一个排列 \(p = (p_i)_{i = 0}^{n - 1}\),记
\[f(p) = \sum_{i = 0}^{n - 1} \sum_{j = i + 1}^{n - 1}(p_j - p_i). \]现在给出 \(N\) 的一个排列 \(p\) 和 \(k,v \in N\),你需要求出 \(N\) 的一个排列 \(q = (q_i)_{i = 0}^{n - 1}\),使得以下条件都成立:
- \(q_k = v\)。
- \(f(p) \equiv f(q) \pmod{n}\)。
或报告无解。
保证 \(n \leq 2 \times 10^5\)。
\(f\) 是容易化简的:
如果再利用上 \(p\) 是排列这一性质的话,还可以进一步化简为
我和一位队友都注意到,如果交换 \(p\) 的第 \(x\) 和第 \(y\) 项得到 \(p'\),会使其函数值变化
因此一直在考虑,要么从 \(p\) 交换出 \(q_k = v\) 后再想办法消除其影响,或直接从顺序交换出 \(q_k = v\) 后再凑出 \(f(q) \equiv f(p) \pmod{n}\)。我甚么办法也没想出来,队友倒是搞出了一种,但没有覆盖到所有情况,导致 WA。
后来我们通过枚举小的数据,观察到都是有解的,因此猜测必定有解,但没有甚么用。
当另一位队友终于写完 J 题大模拟后再看此题时,观察枚举的数据时注意到每个 \(n\) 都有答案可以通过 circular shift(循环移动?)得到,遂出正解。
这里证明一下正确性:设将 \(p\) 循环左移一位得到 \(p'\),有
所以只需通过循环移动使第 \(k\) 位为 \(v\) 即可。时间复杂度 \(O(1)\)。
后来 Gemini 告诉我们,在出现 \(\bmod n\) 时应当优先考虑 circular shift。这是我们没有经验。
inline void solve() {
uint32_t n, idx, val;
std::cin >> n >> idx >> val;
std::vector<uint32_t> perm(n);
uint32_t pos;
for (uint32_t i = 0; i < n; ++i) {
std::cin >> perm[i];
if (perm[i] == val) pos = i;
}
uint32_t lsh = pos - idx + n;
if (lsh >= n) lsh -= n;
for (uint32_t i = lsh; i < n; ++i) {
std::cout << perm[i] << ' ';
}
for (size_t i = 0; i < lsh; ++i) {
std::cout << perm[i] << ' ';
}
std::cout << '\n';
}
G. Precision Error?!
给定 \(n \in \mathbb{N}^*\),需要找出一个点集 \(S \subset \mathbb{R}^3\) 使得
- \(|S| \leq 2 n + 2\)。
- \((\forall P \in S)\ (|\{Q \in S: \Vert\vec{PQ}\Vert_2 = 1\}| = n)\)。
为了允许浮点误差,取精度 \(\epsilon = 0.01\), \(S\) 需要满足
- \((\forall P,Q \in S)\ (P = Q \lor \Vert\vec{PQ}\Vert_2 > \epsilon)\)。
- \(|S| \leq 2 n + 2\)。
- \((\forall P \in S)\ (|\{Q \in S: \Vert\vec{PQ}\Vert_2 \in (1 - \epsilon, 1 + \epsilon)\}| = n)\)。
保证 \(n \leq 100\)。有 \(T \leq 100\) 组测试。
看到题解真气笑了。我就说这个 \(\epsilon\) 怎么这么大,别的题都是 \(10^{-5}\)、\(10^{-6}\),这里来个 \(10^{-2}\),他妈的,果然有蹊跷。
注意到这里的 \(\epsilon\) 相当大,所以我们可以通过构造两部分点,使得同一部分的点之间非常近但不比 \(\epsilon\) 近,而不同部分的点之间的距离都几乎为 \(1\)。
对于平面 \(z = 0\) 上的一个点,在平面 \(z = 1\) 中有一个半径为 \(r = \sqrt{(1 + \epsilon)^2 - 1^2} \approx 0.1418 > 14 \epsilon\) 的圆,这个圆内的点到该点的距离都在 \([1, 1 + \epsilon)\)。这实际上是因为 \(\sqrt{1 + \left(\sqrt{2 \epsilon}\right)^2} = 1 + \epsilon + o(\epsilon^2)\),即圆的半径 \(r \approx \sqrt{2 \epsilon}\)。我们可以在两个平面上各放 \(n\) 个点。为了让两个平面的点互相在对方的容忍范围中,我们需要使它们都位于圆柱 \(x^2 + y^2 \leq \left(\dfrac{1}{2} r\right)^2\) 内(当然,圆心位置实际上是任意的)。
简便起见,考虑将每个平面的点以正方形点阵排布,即用一个 \(\left\lceil \sqrt{n}\right\rceil \times \left\lceil \sqrt{n}\right\rceil\) 点阵排布这 \(n\) 个点。这样的正方形点阵中,设两个点的最近距离(即相邻两点的距离)为 \(d\),则两个点的最远距离为 \(\left(\left\lceil \sqrt{n}\right\rceil - 1\right) \cdot \sqrt{2} d\)。我们希望
解该不等式组得
由 \(n \leq 100\) 得上界
所以完全是可以的。
constexpr double D = 0.011;
constexpr size_t N = 100, S = 10; // sqrt(N)
inline void preprocess() {
std::cout << std::fixed << std::setprecision(9);
}
inline void solve() {
size_t n;
std::cin >> n;
std::cout << (n << 1) << '\n';
for (size_t i = 0; i < n; ++i) {
auto [x, y] = std::div(SC<long long>(i), SC<long long>(S));
for (int z = 0; z < 2; ++z) {
std::cout << (D * x) << ' ' << (D * y) << ' ' << z << '\n';
}
}
}
时间复杂度:\(O(n)\)。
空间复杂度:\(O(1)\)。
C. Fish Eating
在一个 \(m \times n\) 网格上,初始时全是障碍,没有鱼,在之后的若干次操作中会逐渐放置鱼。除了你操作的鱼可以动以外,别的鱼都是静止的。每条鱼有大小。当操作某条鱼时,要么将其移动到鱼已经被吃掉而留下的空白处,要么移动到与它相邻的(四个方向之一)、大小不大于它自己的鱼的位置并将其吃掉。每吃掉一条鱼,自己的大小会增加 \(1\)。
现在进行 \(q\) 次操作,每次会选择下面的某一种操作:
- 给定 \(x,y,v\),表示移走 \((x, y)\) 处的障碍,并放置一条大小为 \(v\) 的鱼。保证该鱼的大小 \(v\) 不小于此前放的任何一条鱼。回答这条鱼现在最多能吃多少条鱼(不会真的吃)。
- 给定 \(x,y\)。设将 \((x, y)\) 处的鱼的大小增大任意值时(不会真的增大),它能吃掉的鱼的数量最大为 \(s\)(不会真的吃)。求出为使该鱼能吃 \(s\) 条鱼,其大小要增大的值的最小值。
保证 \(m \cdot n \leq 2.5 \times 10^5,\ q \leq 5 \times 10^5\)。强制在线处理。
并查集是很容易想到的,因为需要涉及到连通块合并。第一种查询可以容易地用并查集维护。
很容易注意到那个关键的性质:后来的鱼一定不小于已有的鱼。这意味着新加入的鱼的答案可以立刻确定,且对于某一条鱼,它的答案是随着加入的鱼变多不递减(不严格递增)的。比赛时想到这里就不知道怎么办了,仍然只能想出 \(O(q^2)\) 做法。
还有一个关键的性质需要注意到:当两个连通块第一次被一条鱼连在一起时,来自一个连通块的鱼要想到达另一个,必须吃这一条“割边鱼”;即便后面加的鱼能使得这条鱼不再是割边,走这条鱼也不会更劣,因为后加的鱼一定不比他小。这启发我们考虑 Kruskal 重构树的思想(然而在比赛时我并不知道这个东西),维护一个带权并查集。
每条鱼都是并查集的一个顶点。对于顶点 \(x\),设其父节点为 \(p_x\),其权值 \(ans_x\) 为“从这条鱼的位置出发,要吃完它所在连通块的所有鱼,初始时的大小的最小值”,当 \(x\) 为根节点时还要维护其树大小 \(s_x\)。在路径压缩时需要更新 \(v\) 的权值:
而当我们插入新的鱼时,要将与之相邻的连通块都以新鱼为根,并更新这些连通块的根的权值:
对于第二种查询,只需输出 \(\max\{0, ans_i - v_i\}\) 即为答案,不过要先执行一次路径压缩以更新答案。
size_t m, n, tc_num;
std::vector<std::vector<size_t>> map;
std::vector<uint32_t> vals, ans;
std::vector<size_t> prts, szs;
uint32_t last_ans;
inline void preprocess() {
std::cin >> m >> n >> tc_num;
map.resize(m, std::vector<size_t>(n, -1));
auto tot = std::min(m * n, tc_num);
vals.reserve(tot);
ans.reserve(tot);
prts.reserve(tot);
szs.reserve(tot);
}
size_t find(size_t x) {
auto prt = prts[x];
if (prt == x) return x;
auto anc = find(prt);
ans[x] = std::max(ans[x], ans[prt]);
prts[x] = anc;
return anc;
}
inline void solve() {
int op;
uint32_t x, y;
std::cin >> op >> x >> y;
x ^= last_ans, y ^= last_ans;
--x, --y;
if (op == 1) {
assert(map[x][y] == size_t(-1));
auto id = vals.size();
map[x][y] = id;
prts.emplace_back(id);
szs.emplace_back(1);
vals.emplace_back();
std::cin >> vals[id];
ans.emplace_back(0);
constexpr std::array<std::pair<int, int>, 4>
DIRS{{{1, 0}, {0, 1}, {-1, 0}, {0, -1}}};
for (auto [dx, dy] : DIRS) {
ptrdiff_t cur_x = SC<ptrdiff_t>(x) + dx, cur_y = SC<ptrdiff_t>(y) + dy;
if (cur_x < 0 || cur_x >= SC<ptrdiff_t>(m) ||
cur_y < 0 || cur_y >= SC<ptrdiff_t>(n)) continue;
if (map[cur_x][cur_y] == size_t(-1)) continue;
auto rt = find(map[cur_x][cur_y]);
if (rt == id) continue;
prts[rt] = id;
szs[id] += szs[rt];
ans[rt] = std::max<int64_t>(0, SC<int64_t>(vals[id]) - (szs[rt] - 1));
}
last_ans = szs[id] - 1;
} else if (op == 2) {
auto id = map[x][y];
assert(~id);
find(id);
last_ans = std::max<int64_t>(0, SC<int64_t>(ans[id]) - vals[id]);
} else {
assert(false);
}
std::cout << last_ans << '\n';
std::cerr << last_ans << '\n';
}
inline int mainLoop() {
for (size_t tc = 0; tc < tc_num; ++tc) {
solve();
}
return 0;
}
时间复杂度:\(O(m \cdot n + q \log(m \cdot n))\)。如果使用哈希表存储地图,可以优化到 \(O(q \log(m \cdot n))\)。
空间复杂度:\(O(m \cdot n + \min\{m \cdot n, q\})\)。同样,如果用哈希表存地图,可以优化到 \(O(\min\{m\cdot n, q\})\)。
H. Rock-Paper-Scissors Master
Alice 和 Bob 要玩 \(n \in \mathbb{N}\) 轮游戏。牌有石头、剪刀、布三种。两人初始时都各有三张牌,他们的牌始终都是公开的。在每一轮游戏中:
- Alice 选择一张牌打出。Bob 知道他打出了哪一张牌。
- 然后,Bob 也需要选择一张牌打出。
- 按照正常的石头剪刀布规则,比较两人的牌。如果 Alice 赢,他的得分加 \(3\);如果是平局,他的得分加 \(1\);如果 Alice 输了,他的得分不变。
- 已经打出的牌被舍弃。两个玩家各自独立地重新抽一张牌,每个玩家抽到每一种牌的概率都是 \(\dfrac{1}{3}\)。
Alice 需要最大化他的得分,而 Bob 需要最小化 Alice 的得分,他们都采取最优策略。
给定初始牌组和 \(n\),求 Alice 在 \(n\) 轮后的期望分数。要求绝对误差和相对误差都不超过 \(10^{-6}\)。
保证 \(n \leq 10^9\)。一共有 \(T \leq 10^5\) 组测试点。
Markov 决策过程是甚么?
L. Substrings of Substrings
2026 “钉耙编程”中国大学生算法设计暑期联赛(1)
1006. 开关灯
给定权值序列 \((a_i)_{i = 0}^{n - 1} \in \mathbb{N}^n\),表示有 \(n \in \mathbb{N}^*\) 盏灯,初始时都是熄灭的。在 \(\mathbb{N} \cap [0, n)\) 的所有排列中随机选一个记作 \((p_i)_{i = 0}^{n - 1}\),按该顺序依次点亮各灯。设第 \(i \in \mathbb{N} \cap [0, n)\) 步时,所有点亮的灯会形成 \(c_i\) 个极大连续段,则这一步的得分为 \(a_{p_i} \cdot c_i\)。求总得分的期望
\[\mathbb{E}\left(\sum_{i = 0}^{n - 1}a_{p_i} \cdot c_i\right), \]答案对 \(M = 998244353\) 取模。
保证 \(n \leq 2 \times 10^6\),\((\forall i \in \mathbb{N} \cap [0, n))\ (a_i < M)\)。
根据期望的线性性,我们可以将期望表达式转化为
但我们并不知道这个期望怎么推。通过对 \(n \in [3, 10]\) 打表,我注意到(注意力难得惊人),枚举范围内的所有 \(n\) 都满足
其中 \(N(\cdot)\) 表示古典概型计数。
遂猜出答案。真他妈神了。
下面还是严谨地推导一遍。
j将这 \(n\) 个灯从左到右摆一排,则一个极大连续段有且仅有一个左端点。我们可以将连续段计数转换为左端点计数,而一个点是左端点,当且仅当以下条件都成立:
- 该点的灯点亮。
- 该点左侧没有灯或左侧的相邻灯熄灭。
设事件 \(IL_{i, j}\) 表示“灯 \(i\) 被点亮时(即刚过时刻 \(p^{-1}_i\)时)灯 \(j\) 是某个极大连续段的左端点”。于是
利用期望的线性性得
分类讨论 \(IL_{i, j}\):
-
若 \(j = 0\):\(j\) 左侧没有灯,它是左端点当且仅当它亮起。
-
若 \(i = 0\):显然 \(\mathbb{P}(IL_{0, 0}) = 1\)。
-
若 \(i \neq 0\):\(\mathbb{P}(IL_{i, 0}) = \mathbb{P}(p^{-1}_i < p^{-1}_0)\)。因为 \(\vec{p}\) 是随机选取得排列,根据对称性和 \(i \neq 0\),有
\[\mathbb{P}(p^{-1}_i < p^{-1}_0) = \mathbb{P}(p^{-1}_0 < p^{-1}_i) = \dfrac{1}{2}. \]
-
-
若 \(j \neq 0\):
1005. 摩卡数
设 \(\Sigma\) 是字母表(记其中第 \(i \in \mathbb{N} \cap [0, |\Sigma|)\) 个字母为 \(\sigma_i\))。对于字符串 \(s \in \Sigma^n\),记其前缀函数为 \(\pi\),其中
\[\pi_i = \max\{j \in \mathbb{N} \cap [0, i]: s_{[0, j)} = s_{[i - j + 1, i]} \}\ (i \in \mathbb{N} \cap [0, n)). \]现在有算法
\[\begin{array}{rl} 1 & \textbf{func $count(\Sigma, s)$:} \\ 2 & \qquad cnt \gets 0 \\ 3 & \qquad \textbf{for $i \in \mathbb{N} \cap [0, n - 2]$:} \\ 4 & \qquad\qquad \textbf{for $c \in \Sigma$:} \\ 5 & \qquad\qquad\qquad k \gets i \\ 6 & \qquad\qquad\qquad \textbf{while $k > 0 \land s_k \neq c$:} \\ 7 & \qquad\qquad\qquad\qquad cnt \gets cnt + 1 \\ 8 & \qquad\qquad\qquad\qquad k \gets \pi_{k - 1} \\ 9 & \qquad \textbf{return $cnt$} \end{array} \]给定 \(t \in \mathbb{N}^*\),需要选取合适的 \(\Sigma\) 和 \(s \in \Sigma^n\ (n \in \mathbb{N}^*)\),使得 \(count(\Sigma, s) = t\)。
保证 \(t \leq 10^9\),要求 \(|\Sigma| \leq 26\) 且其中的字母从 \(\texttt{a}\) 开始按拉丁字母顺序取,要求 \(n \leq 10^5\)。有不超过 \(50\) 组测试数据。
猜到了只需取 \(\Sigma = \{\texttt{a}, \texttt{b}\}\)。可惜没注意到在连续的 \(\texttt{a}\) 后面放连续的 \(\texttt{b}\) 是甚么效果。
\(count\) 的返回值实际上就是从各个位置出发的错配次数之和,错配时会将指针 \(k\) 按照前缀函数往前跳。
为了简便,先考虑只有一个字母的情况,即 \(\Sigma = \{\texttt{a}\}\)。此时因为都是同一个字母,所以不存在错配,即答案始终为 \(0\)。
那末,接下来考虑两个字母的情况,即 \(\Sigma = \{\texttt{a}, \texttt{b}\}\)。既然限制 \(|\Sigma| \leq 26\),我猜大概率是主要靠 \(s\) 做手脚,字母表取两个字母就够了(在计算理论中,两个字母也是最常用的字母表)。稍微考虑一下也容易发现,更多字母会导致计算答案时乘上因数,这会限制我们的发挥,对我们是很不利的。
在这种字母表下考虑字符串 \(\texttt{a}^n\)。容易发现,此时每个位置都有 \(\pi_i = i + 1\),所以每次错配只会往前跳一步,从 \(i\) 出发会错配 \(i + 1\) 次,所以
此后我考虑了能否通过交替两字母的连续段来构造,失败,因为第二次出现的 \(\texttt{a}\) 段会受第一次的影响,\(\texttt{b}\) 段同理。
实际上,只需要构造 \(\texttt{a}^m\texttt{b}^n\) 就可以。对于 \(\texttt{a}\) 段,它的贡献由上面的公式可以得到,且不会受到 \(\texttt{b}\) 段影响;\(\texttt{b}\) 段因为前缀函数都是 \(0\)(因为字符串开头没有 \(\texttt{b}\)),所以每个 \(\texttt{b}\) 贡献都是 \(1\),而且同样也不会受到前面 \(\texttt{a}\) 的影响。因此,
取 \(m = \max\left\{x \in \mathbb{N}: \dfrac{1}{2} x (x - 1) \leq t\right\} = \left\lfloor\dfrac{1 + \sqrt{8 t + 1}}{2}\right\rfloor\),\(n = t - \dfrac{1}{2} m (m - 1)\) 即可,此时 \(n < m \leq \left\lfloor\dfrac{1 + \sqrt{8 \times 10^9 + 1}}{2}\right\rfloor = 44721 < 5 \times 10^4\),所以 \(m + n < 2m < 10^5\)。
inline uint32_t findMax(uint32_t target) {
constexpr double EPS = 1e-6;
return std::floor((std::sqrt(8 * SC<double>(target) + 1) + 1) / 2 + EPS);
}
inline void solve() {
uint64_t target;
std::cin >> target;
size_t m = findMax(target);
size_t n = target - ((SC<uint64_t>(m) * (m - 1)) >> 1);
std::cout << (m + n) << " 2\n";
for (size_t i = 0; i < m; ++i) std::cout << 'a';
for (size_t i = 0; i < n; ++i) std::cout << 'b';
std::cout << '\n';
}
时间复杂度:\(\Theta(\sqrt{t})\)。
空间复杂度:\(\Theta(1)\)。
2026 牛客暑期多校训练营 2
最菜的一集。
B. Bitwise Maximization
给定 \((a_i) \in \mathbb{N}^n\ (n \in \mathbb{N}^*)\),记 \(N = \mathbb{N} \cap [0, n)\),求
\[\max_{S \subseteq N} \left(\bigoplus_{i \in S} a_i + \bigoplus_{i \in N \setminus S} a_i\right). \]保证 \(n \leq 5 \times 10^5\),\((\forall i \in N)\ (a_i < 2^{30})\)。
三个人想了四小时也没能想出来。首 A 六分钟就过了。太绝望了。
记 \(s = \bigoplus_{i \in S} a_i\)。我们考虑过将原式化为
但然后该怎么办就不知道了。ChatGPT 在这里使用了恒等式
于是原式化为
利用与对异或的分配律
可进一步化为
因为 \(s\) 已为定值,只需选取 \(S \subseteq N\) 最大化该式即可。
题解从另一个角度考虑,代替了与对异或的分配律:\((s)_{(2)}\) 中的 \(1\) 在结果中必然为 \(1\),无需考虑;所以我们只需考虑 \((s)_{(2)}\) 中的为 \(0\) 位,即
\[\left(\bigoplus_{i \in S} a_i\right) \land \neg s = \bigoplus_{i \in S} (a_i \land \neg s). \]
最大子集异或和问题可以用异或线性基解决。我还给别人讲课讲过这个呢,看题解的时候还是没想到,真是废物,误人子弟。
inline void solve() {
constexpr unsigned B = 30;
size_t n;
std::cin >> n;
std::vector<uint32_t> arr(n);
uint32_t sum = 0;
for (auto &e : arr) {
std::cin >> e;
sum ^= e;
}
for (auto &e : arr) e &= ~sum;
std::array<uint32_t, B> bases{};
for (auto e : arr) {
for (unsigned i = B; i--;) {
if ((e >> i) & 1) {
if (!bases[i]) {
bases[i] = e;
break;
}
e ^= bases[i];
}
}
}
uint32_t ans = 0;
for (unsigned i = B; i--;) {
ans = std::max(ans, ans ^ bases[i]);
}
ans = (ans << 1) + sum;
std::cout << ans << '\n';
}
时间复杂度:\(\Theta(Bn)\),其中 \(B = \log(\max \vec{a})\)。
空间复杂度:\(\Theta(n + B)\)。
G. GCD Graph
给定 \(n \in \mathbb{N}^*\)。构造这样一张有向图 \(G = (V, E)\),其中 \(V = [n]\),
\[E = \{(u, v, w) \in V \times V \times \mathbb{N}: u < v \land w = \gcd(u, v)\}. \]记 \(\delta(u, v)\ (u,v \in V,\ u < v)\) 表示从 \(u\) 到 \(v\) 的最短路。给出 \(l, r \in [n]\ (l \leq r < n)\),求
\[\sum_{i = l}^r \delta(i, n). \]保证 \(n \leq 10^7\)。
有不多于 \(100\) 组测试数据。
我枚举几项后注意到
遂想要通过线性筛分解质因数,然后用容斥数出不互质的数的个数。
constexpr uint64_t N = 1e7;
std::vector<bool> not_prime(N + 1);
std::vector<uint64_t> primes;
std::vector<uint64_t> mpfs(N + 1, UINT32_MAX);
inline void preprocess() {
primes.emplace_back(2);
for (uint64_t i = 1; (i << 1) <= N; ++i) {
mpfs[i << 1] = 2;
}
for (uint64_t i = 3; i <= N; i += 2) {
if (!not_prime[i]) {
primes.emplace_back(i);
mpfs[i] = i;
}
for (auto j : primes) {
if (j * i > N) break;
not_prime[j * i] = true;
mpfs[j * i] = j; // j is the minimum prime factor of i * j
if (i % j == 0) break;
}
}
}
inline void solve() {
uint64_t l, r, n;
std::cin >> l >> r >> n;
std::vector<uint64_t> factors;
factors.reserve(7);
for (uint64_t i = n; i > 1;) {
auto mpf = mpfs[i];
factors.emplace_back(mpf);
while (i > 1 && i % mpf == 0) {
i /= mpf;
}
}
uint64_t ans = 0;
assert(factors.size() < 32);
for (uint64_t i = 1; i < (uint64_t(1) << factors.size()); ++i) {
uint64_t prod = 1;
for (unsigned j = 0; j < SC<unsigned>(factors.size()); ++j) {
if (i & (1u << j)) {
prod *= factors[j];
}
}
uint64_t floor = (l + prod - 1) / prod, ceil = r / prod, cnt = ceil - floor + 1;
if (std::popcount(i) & 1) {
ans += cnt;
} else {
ans -= cnt;
}
}
ans += r - l + 1;
std::cout << ans << '\n';
}
很神秘的是,如果我开一个 \(10^7\) 的数组而非 std::vector 的话,牛客会报“Compiler exceeded OUTPUT limit”,不知道甚么鬼。我换到牛客的编译器版本,测了也没有问题,用 Compiler Explorer 也没问题。
很不幸,这次注意力不但没能帮我解题,反而浪费了大量时间在错误的思路上。这个式子在 \(2184\) 以下都没有反例,但从这个数字开始是有许多组的,在 \(10^5\) 范围内有:
2184 2200
27830 27846
32214 32230
57860 57876
62244 62260
87890 87906
92274 92290

浙公网安备 33010602011771号