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

2025CSP-S模拟赛23

T1 T2 T3 T4
30 TLE 4 TLE 20 RE 15 TLE

排名:14/22;总分:69。

T1 第三个包打假了,少 10 分,T2 是大样例不明所以没过,T3 T4 均为部分分。

T1 origen

考虑拆位拆贡献。首先,我们将原式变为 \(\sum_{i=0}^n \sum_{j=i+1}^n(s_i\oplus s_j)^2\),其中 \(s_i\) 是异或前缀和。然后拆位暴拆式子就行了。

\[\sum_{i=0}^n \sum_{j=i+1}^n(s_i\oplus s_j)^2 =\sum_{i=0}^n \sum_{j=i+1}^n(\sum_{k}(c_{i,k}\ne c_{j,k})\times2^k)^2 \]

然后随便维护一下就行了。

#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;
}
const int MOD = 998244353;
const int N = 2e5 + 10, M = 20;
int n, a[N];
int s[N], c[M][2][M][2];
signed main() {
	n = read();
	for (int i = 1; i <= n; i++) {
		a[i] = read();
	}
	for (int i = 1; i <= n; i++) {
		s[i] = s[i - 1] ^ a[i];
	}
	for (int i = 0; i < M; i++)
		for (int j = 0; j < M; j++) c[i][0][j][0] = 1;
	int ans = 0;
	for (int i = 1; i <= n; i++) {
		for (int k1 = 0; k1 < M; k1++) {
			for (int k2 = 0; k2 < M; k2++) {
				int v1 = (s[i] >> k1) & 1, v2 = (s[i] >> k2) & 1;
				ans = (ans + c[k1][v1 ^ 1][k2][v2 ^ 1] * (1 << k1) % MOD * (1 << k2) % MOD) % MOD;
				c[k1][v1][k2][v2]++;
			}
		}
	}
	printf("%lld\n", ans);
	
	return 0;
}

T2 competiton

题解给了三种做法,这边选择了我认为比较好懂的一种做。

考虑正难则反。

首先假设一道题能被重复做多次,那么答案就是:

\[\sum_{i=1}^n(r_i-l_i+1)\times i\times (n-i+1) \]

即一个人能做的题目数量乘上一个人在多少区间中出现。

我们令 \(f_{i,j}\) 表示第 \(i\) 个人前面的最靠右的能做出题目 \(j\) 的人的编号。然后就可以发现 \(i\)\(f_{i,j}\) 在做第 \(j\) 道题时会重复,多出的方案数即为 \(f_{i,j}\times(n-i+1)\)

然后把第一维滚掉,用线段树动态维护 \(f\) 即可。

有一个细节点就是动态开店线段树常数太大了,所以要离散化处理。

#include <bits/stdc++.h>
#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++)
inline 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 MOD = 1e9 + 7;
const int N = 1e6 + 10;
int n;
int m, ll[N], rr[N];
inline int fpow(int a, int x) {
	int ans = 1;
	while (x) {
		if (x & 1) ans = ans * a % MOD;
		a = a * a % MOD;
		x >>= 1;
	}
	return ans;
}
inline int getny(int x) {
	return fpow(x, MOD - 2);
}
int lis[N << 1];
const int M = N << 5;
int s[M], lazy[M];
#define lc p << 1
#define rc p << 1 | 1
#define mid (l + r >> 1)
inline void pushdown(int p, int l, int r) {
	if (!lazy[p]) return;
	s[lc] = (lis[mid] - lis[l - 1]) % MOD * lazy[p] % MOD;
	s[rc] = (lis[r] - lis[mid]) % MOD * lazy[p] % MOD;
	lazy[lc] = lazy[p];
	lazy[rc] = lazy[p];
	lazy[p] = 0;
}
inline void update(int p, int l, int r, int x, int y, int v) {
	if (x == l && r == y) {
		s[p] = (lis[r] - lis[l - 1]) % MOD * v % MOD;
		lazy[p] = v;
		return;
	}
	pushdown(p, l, r);
	if (y <= mid) update(lc, l, mid, x, y, v);
	else if (x > mid) update(rc, mid + 1, r, x, y, v);
	else update(lc, l, mid, x, mid, v), update(rc, mid + 1, r, mid + 1, y, v);
	s[p] = (s[lc] + s[rc]) % MOD;
} 
inline int query(int p, int l, int r, int x, int y) {
	if (x == l && r == y) return s[p];
	pushdown(p, l, r);
	if (y <= mid) return query(lc, l, mid, x, y);
	else if (x > mid) return query(rc, mid + 1, r, x, y);
	else return (query(lc, l, mid, x, mid) + query(rc, mid + 1, r, mid + 1, y)) % MOD;
} 
signed main() {
	n = read(), m = read();
	int tt = 0;
	for (int i = 1; i <= n; i++) {
		ll[i] = read(), rr[i] = read();
		lis[++tt] = ll[i] - 1, lis[++tt] = rr[i];
	}
	sort(lis + 1, lis + 1 + tt);
	int len = unique(lis + 1, lis + 1 + tt) - lis - 1;
	for (int i = 1; i <= n; i++) {
		ll[i] = lower_bound(lis + 1, lis + 1 + len, ll[i] - 1) - lis;
		rr[i] = lower_bound(lis + 1, lis + 1 + len, rr[i]) - lis;
	}
	int ans = 0;
	for (int i = 1; i <= n; i++) {
		ans = (ans + (lis[rr[i]] - lis[ll[i]]) % MOD * i % MOD * (n - i + 1) % MOD) % MOD;
	} 
	int sum = 0;
	for (int i = 1; i <= n; i++) {
		sum = (sum + query(1, 1, len, ll[i] + 1, rr[i]) * (n - i + 1) % MOD) % MOD;
		update(1, 1, len, ll[i] + 1, rr[i], i);
	}
	ans = (ans - sum) % MOD * getny(n * (n + 1) % MOD * getny(2) % MOD) % MOD;
	ans = (ans + MOD) % MOD;
	printf("%lld\n", ans);
	
	return 0;
}

T3 tour

T4 abstract

posted @ 2025-07-21 16:11  Zctf1088  阅读(17)  评论(0)    收藏  举报