2025CSP-S模拟赛35 比赛总结
2025CSP-S模拟赛35
| T1 | T2 | T3 | T4 |
|---|---|---|---|
| 0 RE | 10 TLE | 0 RE | 0 TLE |
总分:10;排名:19/19
事情是这样的。本来,T1 和 T3 没有文件 IO,只有 T2 和 T4 有。然后后来他都加上了,我也没发现。然后我 T1 和 T3 写的 100 多分都没了。
T1 114514
唉这个不想写了。
反正你会发现一个神秘性质,或者叫做统计答案的方式。你就是要找在这个桶中,你把当前的 \(a_i\) 赋值成 1,然后找 \(a_i\) 前最长连续 1 的连续段长度就是这一位能填的数的数量。考场上我是用二分套了个树状数组维护。正解的话你拿个并查集一搞就行了
#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 = 1e9 + 7;
const int N = 4e6 + 10;
int n, a[N];
int fa[N];
int getfa(int x) {
return x == fa[x] ? x : fa[x] = getfa(fa[x]);
}
signed main() {
freopen("trans.in", "r", stdin);
freopen("trans.out", "w", stdout);
n = read();
for (int i = 1; i <= n; i++) a[i] = read();
for (int i = 1; i < N; i++) fa[i] = i;
int ans = 1;
for (int i = 1; i <= n; i++) {
int p = getfa(a[i] - 1);
fa[a[i]] = p;
ans = ans * (a[i] - (p + 1) + 1) % MOD;
}
printf("%lld\n", ans);
return 0;
}
T2 沉默乐园
令 \(\max r_i=m\)。
首先,题意就是给出一种构造使得不存在一对真前缀和真后缀的加和相等。然后你可以发现只要统计不相交的两段即可,因为你相交的两段减去中间等价于不相交的两段。
考虑将前缀和数组和后缀和数组进行归并排序,那么我们只需要判断得到的新序列相邻两项是否相等即可。
考虑用 dp 实现这个过程。\(f_{i,j,k}\) 表示左边选到第 \(i\) 位,右边到第 \(j\) 位,且此时的前缀和减去后缀和等于 \(k\)。转移的话你考虑到你是去归并排序,所以你每次是要给更小的那边加上,即:
\[f_{i,j,k}\rightarrow f_{i+1,j,k+x}(k<0,x\in [l_{i+1},r_{i+1}],k+x\ne 0)\\
f_{i,j,k}\rightarrow f_{i,j-1,k-x}(k<0,x\in [l_{j-1},r_{j-1}],k-x\ne 0)
\]
然后边界显然,\(f_{0,n+1,0}=1\)。答案即为 \(\sum \sum f_{i,i+1,k}\)。
然后搞一个差分优化一下就好了。
#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 = 1e9 + 7;
const int N = 50 + 10, M = 2005 + 10;
int n, l[N], r[N];
int f[N][N][M << 1];
il void upd(int &a, int b) {
a = (a + b) % MOD;
}
signed main() {
freopen("orchestra.in", "r", stdin);
freopen("orchestra.out", "w", stdout);
n = read();
for (int i = 1; i <= n; i++) {
l[i] = read(), r[i] = read();
}
f[0][n + 1][0 + M] = 1;
f[0][n + 1][1 + M] = -1;
for (int i = 0; i < n; i++) {
for (int j = n + 1; j > i; j--) {
for (int k = -2000; k <= 2000; k++) {
upd(f[i][j][k + M], f[i][j][k - 1 + M]);
}
for (int k = -2000; k < 0; k++) {
upd(f[i + 1][j][k + l[i + 1] + M], f[i][j][k + M]);
upd(f[i + 1][j][k + r[i + 1] + 1 + M], -f[i][j][k + M]);
if (k + l[i + 1] <= 0 && k + r[i + 1] >= 0) {
upd(f[i + 1][j][0 + M], -f[i][j][k + M]);
upd(f[i + 1][j][1 + M], f[i][j][k + M]);
}
}
for (int k = 0; k <= 2000; k++) {
upd(f[i][j - 1][k - r[j - 1] + M], f[i][j][k + M]);
upd(f[i][j - 1][k - l[j - 1] + 1 + M], -f[i][j][k + M]);
if (k - r[j - 1] <= 0 && k - l[j - 1] >= 0) {
upd(f[i][j - 1][0 + M], -f[i][j][k + M]);
upd(f[i][j - 1][1 + M], f[i][j][k + M]);
}
}
}
}
int ans = 0;
for (int i = 0; i <= n; i++) {
for (int k = -2000; k <= 2000; k++) {
ans = (ans + f[i][i + 1][k + M]) % MOD;
}
}
printf("%lld\n", (ans + MOD) % MOD);
return 0;
}

浙公网安备 33010602011771号