CSP-S模拟赛加赛 比赛总结

CSP-S模拟赛加赛

T1 T2 T3 T4
100 AC 60 RE 15 TLE 37 WA

总分:212;排名:4/5。

T1 A 了,T2 部分分,T3 挂了 20 分,T4 干了 1.5h,思路基本正确,码力太差细节太多,最后输出 0。

T1 Divisors

不难,不说了。

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

using namespace std;

const int bufsz = 1 << 20;
char ibuf[bufsz], *p1 = ibuf, *p2 = ibuf;
#define getchar() (p1 == p2 && (p2 = (p1 = ibuf) + fread(ibuf, 1, bufsz, stdin), p1 == p2) ? EOF : *p1++)
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;
}
bool Beg;
const int N = 200 + 10;
int n, m, a[N];
int p[20000000], tot;
int ans[N];
bool End;
il void Usd() {cerr << "\nUse: " << (&Beg - &End) / 1024.0 / 1024.0 << "MB " << (double)clock() * 1000.0 / CLOCKS_PER_SEC << "ms\n";}
signed main() {
	n = read(), m = read();
	for (int i = 1; i <= m; i++) {
		a[i] = read();
	}
	for (int i = 1; i <= m; i++) {
		for (int j = 1; j * j <= a[i] && j <= n; j++) {
			if (a[i] % j == 0) {
				p[++tot] = j;
				if (a[i] / j <= n) p[++tot] = a[i] / j;
			}
		}
	}
	sort(p + 1, p + 1 + tot);
	tot = unique(p + 1, p + 1 + tot) - p - 1;
	for (int i = 1; i <= tot; i++) {
		int cnt = 0;
		for (int j = 1; j <= m; j++) {
			cnt += (a[j] % p[i] == 0);
		}
		ans[cnt]++;
	}
	ans[0] = n;
	for (int k = 1; k <= m; k++) ans[0] -= ans[k];
	for (int k = 0; k <= m; k++) {
		printf("%d\n", ans[k]);
	}
	Usd();
	return 0;
}

T2 Market

\(t\) 排序依次处理得思路不难想到,跑朴素得 01 背包即可。

正解算一个有点类似与背包的 dp。\(f_i\) 表示价值为 \(i\) 的最小花费。这就很巧妙地解决了 \(M_i\)\(c_i\) 过大得问题。令 \(g_i=\min_{j=i}^V f_j\),即 \(f\) 的后缀最小值。查询就是在 \(g\) 上 lower_bound 即可。其实不难。

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

using namespace std;

const int bufsz = 1 << 20;
char ibuf[bufsz], *p1 = ibuf, *p2 = ibuf;
#define getchar() (p1 == p2 && (p2 = (p1 = ibuf) + fread(ibuf, 1, bufsz, stdin), p1 == p2) ? EOF : *p1++)
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;
}
bool Beg;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 300 + 10, M = 1e5 + 10, maxn = 90000 + 10;
int n, m;
struct node {
	int c, v, t;
	il bool operator < (const node & cmp) const {
		return t < cmp.t;
	}
} a[N];
struct nodeq {
	int t, m, id;
	il bool operator < (const nodeq & cmp) const {
		return t < cmp.t;
	}
} qq[M];
int f[maxn], mn[maxn];
int ans[M];
bool End;
il void Usd() {cerr << "\nUse: " << (&Beg - &End) / 1024.0 / 1024.0 << "MB " << (double)clock() * 1000.0 / CLOCKS_PER_SEC << "ms\n";}
signed main() {
	n = read(), m = read();
	for (int i = 1; i <= n; i++) {
		int c = read(), v = read(), t = read();
		a[i] = {c, v, t};
	}
	for (int i = 1; i <= m; i++) {
		int t = read(), mm = read();
		qq[i] = {t, mm, i};
	}
	sort(a + 1, a + 1 + n);
	sort(qq + 1, qq + 1 + m);
	a[n + 1].t = INF;
	int sum = 0;
	for (int i = 1; i <= n; i++) sum += a[i].v;
	for (int i = 1; i <= sum; i++) f[i] = INF;
	for (int i = 0; i < maxn; i++) mn[i] = INF;
	for (int i = 1, j = 1; j <= m; i++) {
		for (; j <= m && qq[j].t < a[i].t; j++) {
			ans[qq[j].id] = upper_bound(mn, mn + 1 + sum, qq[j].m) - mn - 1;
		}
		if (j > m) break;
		for (int k = sum; k >= a[i].v; k--) {
			f[k] = min(f[k], f[k - a[i].v] + a[i].c);
		}
		for (int k = sum; k >= 0; k--) {
			mn[k] = min(f[k], mn[k + 1]);
		}
	}
	for (int i = 1; i <= m; i++) {
		printf("%lld\n", max(0ll, ans[i]));
	}
	Usd();
	return 0;
}

T3 连通性

o_251020115717_22222.png (743×675) (cnblogs.com)

o_251020115717_11111.png (739×487) (cnblogs.com)

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

using namespace std;

const int bufsz = 1 << 20;
char ibuf[bufsz], *p1 = ibuf, *p2 = ibuf;
#define getchar() (p1 == p2 && (p2 = (p1 = ibuf) + fread(ibuf, 1, bufsz, stdin), p1 == p2) ? EOF : *p1++)
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;
}
bool Beg;
const int MOD = 1e9 + 7;
const int N = 100 + 10;
int n, m;
int fact[N], ny[N];
il int fpow(int a, int x) {
	a %= MOD;
	int ans = 1;
	while (x) {
		if (x & 1) ans = ans * a % MOD;
		a = a * a % MOD;
		x >>= 1;
	}
	return ans;
}
il int C(int n, int m) {
	return n < m ? 0 : fact[n] * ny[m] % MOD * ny[n - m] % MOD;
}
int f[N][N], g[N]; 
bool End;
il void Usd() {cerr << "\nUse: " << (&Beg - &End) / 1024.0 / 1024.0 << "MB " << (double)clock() * 1000.0 / CLOCKS_PER_SEC << "ms\n";}
signed main() {
	fact[0] = 1;
	n = 100;
	for (int i = 1; i <= n; i++) fact[i] = fact[i - 1] * i % MOD;
	ny[n] = fpow(fact[n], MOD - 2);
	for (int i = n - 1; i >= 0; i--) ny[i] = ny[i + 1] * (i + 1) % MOD;
	for (int i = 0; i <= n; i++) f[i][0] = fpow(2, C(i, 2));
	for (int i = 1; i <= n; i++) {
		g[i] = f[i][0];
		for (int j = 1; j < i; j++) {
			g[i] = (g[i] - g[j] * C(i - 1, j - 1) % MOD * f[i - j][0] % MOD) % MOD;
		}
		g[i] = (g[i] + MOD) % MOD;
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= i; j++) {
			for (int k = 1; k <= j; k++) {
				f[i][j] = (f[i][j] + f[i - k][j - k] * C(j - 1, k - 1) % MOD) % MOD;
				for (int l = 1; l <= i - j; l++) {
					f[i][j] = (f[i][j] + f[i - k - l][j - k] * C(j - 1, k - 1) % MOD * C(i - j, l) % MOD * f[k][0] % MOD * g[l] % MOD * fpow(fpow(2, l) - 1, k) % MOD) % MOD;
				}
			}
		}
	}
	int qq = read();
	while (qq--) {
		n = read(), m = read();
		printf("%lld\n", (f[n][m] + MOD) % MOD);
	}
	Usd();
	return 0;
}

T4 树

其实考场上就想到了,但是没码出来。

对于每条链,我们给他一个颜色 \(v_i\)。考虑做一个树剖套线段树,线段树每一个节点维护当前这个点的颜色是什么,即 \(tree[p].c \in \pm v_{i\in[1,m]}\)。正负分别代表他是向上或向下(具体的不重要,只要区分开就行)。对于每种颜色进行并查集(即视作 \(m\) 个点),然后对于每种颜色维护 \(sta_x \in \{1,-1\}\),表示 \(x\)\(fa_x\) 的颜色是否相同。然后对于没条链进行树链修改,在线段树 pushup 的同时进行颜色的合并。那么一个点实际的颜色就是 \(tree[p].c \times sta[|c|]\)。然后在此过程中如有 \(fa_{|x|}=fa_{|y|} \land x=-y\) 的情况即为无解。在线段树更新信息的过程中维护即可。

统计答案比较简单。假设并查集最后有 \(a\) 个连通块,\(b\) 个点到最后没有颜色,那么 \(ans=2^{a+b}\)

代码细节比较多,但是没码出来。

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

using namespace std;

const int bufsz = 1 << 20;
char ibuf[bufsz], *p1 = ibuf, *p2 = ibuf;
#define getchar() (p1 == p2 && (p2 = (p1 = ibuf) + fread(ibuf, 1, bufsz, stdin), p1 == p2) ? EOF : *p1++)
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;
}
bool Beg;
#define abs(x) (x > 0 ? x : -x)
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int N = 3e5 + 10;
int n, m;
vector<int> G[N];
il void Stop() {
	printf("0\n");
	exit(0);
}
int id[N], tot, top[N], siz[N], son[N], dep[N], fa[N];
il void dfs1(int x, int father) {
	fa[x] = father;
	dep[x] = dep[fa[x]] + 1;
	siz[x] = 1;
	for (int y : G[x]) {
		if (y == fa[x]) continue;
		dfs1(y, x);
		siz[x] += siz[y];
		if (siz[y] > siz[son[x]]) son[x] = y;
	}
}
il void dfs2(int x, int t) {
	top[x] = t;
	id[x] = ++tot;
	if (!son[x]) return;
	dfs2(son[x], t);
	for (int y : G[x]) {
		if (y == fa[x] || y == son[x]) continue;
		dfs2(y, y);
	}
}
il int getlca(int x, int y) {
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		x = fa[top[x]];
	}
	if (dep[x] < dep[y]) swap(x, y);
	return y;
}
int f[N], sta[N];
il int getfa(int x) {
	if (x == f[x]) return x;
	int r = getfa(f[x]);
	sta[x] *= sta[f[x]];
	return f[x] = r;
}
struct node {
	int l, r, c, lazy;
} tree[N << 2];
#define lc p << 1
#define rc p << 1 | 1
il void build(int p, int l, int r) {
	tree[p].l = l, tree[p].r = r;
	if (l == r) return;
	int mid = (l + r) >> 1;
	build(lc, l, mid), build(rc, mid + 1, r);
}
il void pushdown(int p) {
	if (!tree[p].lazy) return;
	tree[lc].lazy = tree[p].lazy;
	tree[rc].lazy = tree[p].lazy;
	tree[lc].c = tree[p].c;
	tree[rc].c = tree[p].c;
	tree[p].lazy = 0;
	return;
}
il int query(int p, int x) {
	if (tree[p].l == tree[p].r) return tree[p].c;
	pushdown(p);
	int mid = (tree[p].l + tree[p].r) >> 1;
	if (x <= mid) return query(lc, x);
	else return query(rc, x);
}
il void pushup(int p) {
	if (!tree[lc].c || !tree[rc].c) {
		tree[p].c = tree[lc].c + tree[rc].c;
	} else if (tree[lc].c == tree[rc].c) {
		tree[p].c = tree[lc].c;
	} else {
		tree[p].c = INF;
	}
}
il void upd(int p, int l, int r, int c) {
	if (!tree[p].c) {
		tree[p].c = c;
		tree[p].lazy = c;
	} else if (tree[p].c != INF) {
		int x = getfa(abs(c)), y = getfa(abs(tree[p].c));
		int cx = c * sta[abs(c)], cy = tree[p].c * sta[abs(tree[p].c)];
		if (x != y) {
			f[y] = x;
			if (1ll * cx * cy < 0) {
				sta[y] = -1;
			} else {
				sta[y] = 1;
			}
		} else if (x == y && 1ll * cx * cy < 0) {
			Stop();
		}
		tree[p].c = cx;
		tree[p].lazy = cx;
	} else {
		pushdown(p);
		int mid = (l + r) >> 1;
		upd(lc, l, mid, c);
		upd(rc, mid + 1, r, c);
		pushup(p);
	}
}
il void update(int p, int l, int r, int c) {
	if (l > r) return;
	if (tree[p].l == l && tree[p].r == r) {
		upd(p, l, r, c);
		return;
	}
	pushdown(p);
	int mid = (tree[p].l + tree[p].r) >> 1;
	if (r <= mid) update(lc, l, r, c);
	else if (l > mid) update(rc, l, r, c);
	else update(lc, l, mid, c), update(rc, mid + 1, r, c);
	pushup(p);
}
il void update_path(int x, int y, int v) {
	int lca = getlca(x, y);
	sta[v] = 1;
	while (top[x] != top[y]) {
		if (dep[top[x]] > dep[top[y]]) {
			update(1, id[top[x]] + (top[x] == lca), id[x], v);
			x = fa[top[x]];
		} else {
			update(1, id[top[y]] + (top[y] == lca), id[y], -v);
			y = fa[top[y]];
		}
	}
	if (dep[x] > dep[y]) {
		update(1, id[y] + 1, id[x], v);
	} else {
		update(1, id[x] + 1, id[y], -v);
	}
}
int vis[N];
bool End;
il void Usd() {cerr << "\nUse: " << (&Beg - &End) / 1024.0 / 1024.0 << "MB " << (double)clock() * 1000.0 / CLOCKS_PER_SEC << "ms\n";}
signed main() {
	n = read(), m = read();
	for (int i = 1; i < n; i++) {
		int x = read(), y = read();
		G[x].push_back(y);
		G[y].push_back(x);
	}
	dfs1(1, 0);
	dfs2(1, 1);
	build(1, 1, n);
	for (int i = 1; i <= m; i++) f[i] = i;
	for (int i = 1; i <= m; i++) {
		int x = read(), y = read();
		update_path(x, y, i);
	}
	int cnt = 0;
	for (int i = 1; i <= m; i++) {
		int x = getfa(i);
		if (!vis[x]) {
			cnt++;
			vis[x] = 1;
		}
	}
	long long ans = 1;
	for (int i = 1; i <= cnt; i++) {
		ans = ans * 2 % MOD;
	}
	for (int i = 2; i <= n; i++) {
		if (query(1, id[i]) == 0) {
			ans = ans * 2 % MOD;
		}
	}
	printf("%lld\n", ans);
	Usd();
	return 0;
}
posted @ 2025-10-19 21:38  Zctf1088  阅读(21)  评论(0)    收藏  举报