2025CSP-S模拟赛24 比赛总结

2025CSP-S模拟赛24

T1 T2 T3 T4
20 WA 0 WA 20 TLE 0TLE

排名:14/22;总分:40

T1 傻逼构造,构造炸了。T2 不会,T3 暴力,T4 暴力挂了。

T1 构造

傻逼构造。

#include <bits/stdc++.h>
#define il inline

using namespace std;

il int read() {
	int x = 0; char ch = getchar(); bool t = 0;
	while (ch < '0' || ch > '9') {t ^= ch == '-'; ch = getchar();}
	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();}
	return t ? -x : x;
}
const int N = 2300, M = 50;
int n;
int a[M][M];
int main() {
	n = read();
	int cnt = 0, h = 40, w = 40;
	for (int i = 1; i <= h; i++)
		for (int j = 1; j <= w; j++) a[i][j] = 1;
	int k = 0;
	for (k = 0; k < 9 && cnt + 232 <= n; k++) {
		int i = k * 4;
		for (int j = 1; j <= w; j++) a[i + 1][j] = 1;
		for (int j = 1; j <= w; j++) a[i + 2][j] = 2;
		for (int j = 1; j <= w; j++) a[i + 3][j] = 3;
		for (int j = 1; j <= w; j++) a[i + 4][j] = 2;
		cnt += 232;
	}
	int l1 = k * 4 + 1, l2 = k * 4 + 2, l3 = k * 4 + 3;
	for (int i = 1; i <= w; i++) {
		a[l1][i] = 1;
	}
	if (n - cnt <= 3) {
		for (int i = 1; i <= w && cnt < n; i += 4) {
			a[h][i] = 1, a[h][i + 1] = 2, a[h][i + 2] = 3;
			cnt++;
		}
		for (int i = 1; i <= w && cnt < n; i += 4) {
			a[h][i + 3] = 2;
			cnt++;
		}
	} else {
		a[l2][1] = 2, a[l3][1] = 3;
		a[l2][2] = 2, a[l3][2] = 3;
		cnt += 3;
		int j;
		for (j = 3; j < w && cnt + 3 <= n; j++) {
			a[l2][j] = 2, a[l3][j] = 3;
			cnt += 3;
		}
		if (n - cnt >= 2 && j == w) {
			a[l2][j] = 2, a[l3][j] = 3;
			cnt += 2;
		}
		if (n - cnt >= 3 && j < w) {
			a[l2][j] = 2, a[l3][j] = 3;
			cnt += 3;
		}
	}
	if (n - cnt > 13 && k < 9) {
		l1 += 3, l2 += 3, l3 += 3;
		for (int i = 1; i <= w; i++) {
			a[l1][i] = 1;
		}
		a[l2][1] = 2, a[l3][1] = 3;
		a[l2][2] = 2, a[l3][2] = 3;
		cnt += 3;
		int j;
		for (j = 3; j < w && cnt + 3 <= n; j++) {
			a[l2][j] = 2, a[l3][j] = 3;
			cnt += 3;
		}
		if (n - cnt >= 2 && j == w) {
			a[l2][j] = 2, a[l3][j] = 3;
			cnt += 2;
		}
		if (n - cnt >= 3 && j < w) {
			a[l2][j] = 2, a[l3][j] = 3;
			cnt += 3;
		}
	}
	for (int i = 1; i < w && cnt < n; i += 3) {
		for (int i = 1; i <= w && cnt < n; i += 4) {
			a[h][i] = 1, a[h][i + 1] = 2, a[h][i + 2] = 3;
			cnt++;
		}
		for (int i = 1; i <= w && cnt < n; i += 4) {
			a[h][i + 3] = 2;
			cnt++;
		}
	} 
	printf("%d %d\n", h, w);
	for (int i = 1; i <= h; i++) {
		for (int j = 1; j <= w; j++) {
			if (a[i][j] == 1) printf("r");
			if (a[i][j] == 2) printf("y");
			if (a[i][j] == 3) printf("x");
		}
		printf("\n");
	}
	
	return 0;
}

T2 游戏

傻逼二极管题(全场不是 100 就是 0)。

二分答案 \(mid\),我们只关注学生能否使得被抓人数 \(\le mid\)

那么,人数 \(\le mid\) 的实验室就无关紧要了,我们只考虑人数大于 \(mid\) 的实验室。设同学有 \(p_i\) 的概率进入这个实验室,那么老师如果进入这个实验室抓到人的期望就是 \((1-p_i)\times a_i\)。所以我们要求对于任意这样的 \(a_i\),都有 \((1-p_i)\times a_i\le mid\),据此求出 \(p_i\) 的下界,判断全加起来到不到 \(1\) 即可。

没了。

#include <bits/stdc++.h>
#define il inline

using namespace std;

il int read() {
	int x = 0; char ch = getchar(); bool t = 0;
	while (ch < '0' || ch > '9') {t ^= ch == '-'; ch = getchar();}
	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();}
	return t ? -x : x;
}
const double eps = 1e-12;
const int N = 30 + 10;
int n, a[N];
il bool check(double mid) {
	double p = 0;
	for (int i = 1; i <= n; i++) {
		if (a[i] > mid) {
			p += 1.0 - mid * 1.0 / a[i];
		}
	}
	return p >= 1;
}
int main() {
	n = read();
	int mx = 0;
	for (int i = 1; i <= n; i++) {
		a[i] = read();
		mx = max(mx, a[i]);
	}
	double L = 0, R = mx, ans = 0;
	while (L + eps < R) {
		double mid = (L + R) / 2.0;
		if (check(mid)) {
			ans = mid;
			L = mid;
		} else {
			R = mid;
		}
	}
	printf("%.12lf\n", ans);
	
	return 0;
}

T3 数数

T4 滈葕

出题人也是人才。

据 UKE_Automation 所说(本题英文名为 dopetobly):

这个题目标题和英文令人捉摸不透,考虑进行搜索,然后发现汉字标题和英文都不是一个有意义的词,所以需要进行一些脑洞。考虑谐音,发现这两个字都是多音字,也很难看出其真正含义。真正的突破口在于这个不存在的英文单词,注意到将字母重排后可以得到单词 bloodtype,即血型,并且正好可以和前面的汉字对应,所以我们确定了题目标题想表达的含义是血型。

这是题解给的一段资料:

ABO 血型系统是血型系统的一种,把血液分为 A,B,AB,O 四种血型。血液由红细胞和血清等组成,红细胞表面 有凝集原,血清内有凝集素。根据红细胞表面有无凝集原 A 和 B 来划分血液类型。红细胞上只有凝集原 A 的 为 A 型血,其血清中有抗 B 凝集素;红细胞上只有凝集原 B 的为 B 型血,其血清中有抗 A 凝集素;红细胞上 两种凝集原都有的为 AB 型血,其血清中无凝集素;红细胞上两种凝集原皆无者为 O 型,其血清中两种凝集素 皆有。有凝集原 A 的红细胞可被抗 A 凝集素凝集;有凝集原 B 的红细胞可被抗 B 凝集素凝集。配血试验是两 个人分别提供红细胞和血清并将其混合,观察是否有凝集反应。

然后,我们发现,A,B,C,D 的点权可以分别代表 A,B,AB,O 型血,然后一条边代表一次配血试验,边权表示是否发生凝集。

考虑将一种血型拆成“X 凝集原 + 抗 Y 凝集素”的形式,由于同种凝集原和同种凝集素不能同时出现,那么我们就把这道题转化成了一个 2-SAT 问题(小编觉得这种做法非常巧妙,于是去学习了 2-SAT)。对每一个点设置 \(a_i,b_i\),分别表示是否含有 A/B 凝集原。对每一条边根据是否发生凝集列出与或式,然后跑 2-SAT 就行了。具体的:

显然 A 凝集原和抗 A 凝集素相遇的条件是 \(a_x \wedge \neg a_y\),B 种同理。那么,每次配血试验写下来就是:\(w=(a \wedge \neg a_y) \vee (b_x \wedge \neg b_y)\)

\(w=0\),则有 \(\neg\left(a_{x} \wedge \neg a_{y}\right) \wedge \neg\left(b_{x} \wedge \neg b_{y}\right)=\left(\neg a_{x} \vee a_{y}\right) \wedge\left(\neg b_{x} \vee b_{y}\right)\)

\(w=1\),则有 $\left(a_{x} \wedge \neg a_{y}\right) \vee\left(b_{x} \wedge \neg b_{y}\right)=\left(a_{x} \vee b_{x}\right) \wedge\left(a_{x} \vee \neg b_{y}\right) \wedge\left(\neg a_{y} \vee b_{x}\right) \wedge\left(\neg a_{y} \vee \neg b_{y}\right) $。

#include <bits/stdc++.h>
#define il inline

using namespace std;

il int read() {
	int x = 0; char ch = getchar(); bool t = 0;
	while (ch < '0' || ch > '9') {t ^= ch == '-'; ch = getchar();}
	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();}
	return t ? -x : x;
}
const int N = 2e6 + 10;
int n, m;
vector<int> G[N];
il int P(int x, int a) {return a ? x + n : x;}
il int V(int x, int a) {return a ? x : x + 2 * n;}
il void add(int x, int a, int y, int b) {
	G[V(x, a ^ 1)].push_back(V(y, b));
	G[V(y, b ^ 1)].push_back(V(x, a));
}
int dfn[N], low[N], tot, inst[N], st[N], head, scc[N], cnt;
il void tarjan(int x) {
	dfn[x] = low[x] = ++tot;
	st[++head] = x;
	inst[x] = 1;
	for (int y : G[x]) {
		if (!dfn[y]) {
			tarjan(y);
			low[x] = min(low[x], low[y]);
		} else if (inst[y]) {
			low[x] = min(low[x], dfn[y]);
		}
	}
	if (dfn[x] == low[x]) {
		cnt++;
		while (true) {
			int y = st[head--];
			inst[y] = 0;
			scc[y] = cnt;
			if (x == y) break;
		} 
	}
}
int main() {
	n = read(), m = read();
	for (int i = 1; i <= m; i++) {
		int x = read(), y = read(), w = read();
		if (w == 0) {
			add(P(x, 0), 0, P(y, 0), 1);
			add(P(x, 1), 0, P(y, 1), 1);
		} else {
			add(P(x, 0), 1, P(x, 1), 1);
			add(P(x, 0), 1, P(y, 1), 0);
			add(P(y, 0), 0, P(x, 1), 1);
			add(P(y, 0), 0, P(y, 1), 0);
		}
	}
	for (int i = 1; i <= 4 * n; i++) {
		if (!dfn[i]) tarjan(i);
	}
	for (int i = 1; i <= n * 2; i++) {
		if (scc[i] == scc[i + n * 2]) {
			printf("NO\n");
			return 0;
		}
	}
	printf("YES\n");
	for (int i = 1; i <= n; i++) {
		int aa = (scc[i + 2 * n] < scc[i]);
		int bb = (scc[i + n + 2 * n] < scc[i + n]);
		if (aa && !bb) printf("B");
		if (!aa && bb) printf("A");
		if (aa && bb) printf("D");
		if (!aa && !bb) printf("C");
	}
	
	return 0;
}
posted @ 2025-07-22 14:29  Zctf1088  阅读(49)  评论(0)    收藏  举报