5.1考试总结

30 + 0 + 30 + 0 = 60

考场

拿到题先把 4 道题看了一遍。T1 + T4 博弈论感觉不可做,T2 和 T3 两道计数题感觉可以写暴力。

T1 看到题,看到 \(p_{p_i}\) 就想到了建图,这也是当时 C1 题目的 trick。所以我们可以建边找出所有的环。但是关于环长的 SG 函数就一直没推出来。后来下发了一个单独环的代码,发现 \(sg_5 = sg_{13} = 1\),但依旧不知道怎么弄。想了约 1.5h 毫无进展遂开 T2。

T2 是个计数,看到 \(2^n\) 的子集枚举和部分分却是 \(n \le 1000\),感觉没有得分欲望,遂开 T3,发现是 mex,题目清晰,于是写了 30 分的暴力,目前已经 2.5h。

T4 看了看是线段树,不过有一定想法:发现题目中有 \(y\in[x,\min(k,x+m)]\) 的限制, 而 \(m\le5\),所以大概率是博弈论 + 倒序dp,不过没写出来遂放弃。

最后 1h 草草写完了 T1 的暴力,一共就 60 分,感觉自己炸了。

赛后

本来第一次测的时候我只有 30 分,T1 爆 0 了,以为自己连暴力都能写错,但 std 又又又又又出锅了,重测后拿到 30。
T1 结果是打表题,但其实 sg 函数的式子我也没推出来,\(sg_i = mex_{j=0}^{i-1} (sg_j \oplus sg_{i-j-1})\)。暴力打表发现数据范围内只有环长为 \(1,2,5,13,21,31,47,73,99,125,151,177,315,409\) 的先手必胜,特判即可。

#include<bits/stdc++.h>
using namespace std;
const int M = 5e5 + 5;
bool vis[M];
int p[M];
int main() {
	int T;
	scanf("%d", &T);
	while (T--) {
		int n, ans = 0;
		scanf("%d", &n);
		for (int i = 1; i <= n; i++) {
			scanf("%d", &p[i]);
			vis[i] = 0;
		}
		for (int i = 1; i <= n; i++) {
			if (!vis[i]) {
				int cyc = 0, j = i;
				while (!vis[j]) {
					vis[j] = 1;
					j = p[j];
					cyc++;
				}
				if (cyc == 1 || cyc == 2 || cyc == 5 || cyc == 13 || cyc == 21 || cyc == 31 || cyc == 47 || cyc == 73 || cyc == 99 || cyc == 125 || cyc == 151 || cyc == 177 || cyc == 315 || cyc == 409) ans ^= 1; //雷霆
			}
		}
		if (ans) printf("Y\n");
		else printf("N\n");
	}
	return 0;
}

T2 + T4疯狂计数,以后练。T4 似乎思考方向正确?

T3很巧妙的题,给一个机房大佬的题解:link

posted @ 2026-05-01 23:33  nick_zha  阅读(9)  评论(0)    收藏  举报