【比赛】2023 CSP-S 备战
2023 CSP-S 备战
赛后总结
得分:90 + 35 + 0 + 0
- 惨烈……
- T1 看完题的瞬间发现是大水题,于是直接开打,结果 10min 中打完,调了 20min,最后同时拨相邻的情况还没改过来。
- T2 没有吸取 T1 的教训,甚至失误的更严重,感觉是个并查集,算法把样例手推过了之后,又花了 40min 多调试,大样例死活过不了。最后稍微细想了一下,就把这个做法 Hack 了。耽误太多时间,最后还是 5min 打了个很水的暴力。
- 当时心态其实就有点问题了,再加之电脑时间被调快了一个小时,心态更炸了,于是直接开了 “小有挑战” 的 T3。结果就是 T3,打到一半,电脑上时间已经交卷了(实际上还有 1 个小时),才发现时间快了,稍微稳住了一点,重新把 T3 的打法梳理了一遍,但最终还是没打完。(RE 0 pts)
考试策略
- 20min 左右通读题面(一定不要读错题,结合样例分析
- 每道题题至少保证 50pts 左右的暴力
- 不必按照顺序做题,那道题最有希望先做哪道
- 随时存盘
- 时间分配
- 注重暴力(特别是没有思路的时候,有时间就打
- 不要在没把握的的,耗费太长时间
- 80pts - 100pts 都可以认为是正解(不要优化常数
- 先想再写
- 对拍
- 好写的对拍哪怕是暴力也好写暴力
- 不要太以来大数据
- 对拍以验证正确性为目的(不要用于验证性能
- 重视静态差错
- 宁愿少开空间,也不要 MLE(算好空间
- 最后 15min 不要打新的代码(文件输入输出,
- 中途感觉前一半时间荒废了,不要再想以前浪费的时间了。调整好心态
- 及时调整预期得分
- 相信自己!!!
一些链接
备忘
知识点补漏
数学常用结论
\(\large\star\) KMP
-
\(nxt\) 数组的求法
nxt[1] = 0; for (int i = 2; i <= n; i++) { int j = nxt[i-1]; while (j && s[i] != s[j+1]) j = nxt[j]; // 记得这的 j 不须 -1 nxt[i] = j + (s[i] == s[j+1]); }
-
时间复杂度证明:
\(j\) 每次至少减少 1,而且减少总次数不会超过当前 \(j\) 增加总次数。而 \(j\) 最多增加 \(n\) 次,那么最多就减少 \(n\) 次,故时间复杂度为 \(O(n)\)。
联通分量
-
low[i]
定义:在 本次dfs 已遍历过的点中,dfn
的最小值。 -
板板
void Tarjan (int u) { st[++st[0]] = u, low[u] = dfn[u] = ++_dfn; for (int v : G[u]) if (!dfn[v]) Tarjan(v), low[u] = min(low[u], low[v]); else if (!scc[v]) // !!! 如果 v 已经属于一个连通块内了,你还要去找她更新干嘛??? low[u] = min(low[u], dfn[v]); if (low[u] == dfn[u]) { ++_scc; do scc[st[st[0]--]] = _scc; while (st[st[0]+1] != u); } }
-
\(\large\star\) 缩点以后图当然是 DAG,但是不一定没有重边【最大半连通子图】
最短路
CRT & ExCRT
卢卡斯 Lucas
\[\binom{n}{m}\bmod p = \binom{\left\lfloor n/p \right\rfloor}{\left\lfloor m/p\right\rfloor}\cdot\binom{n\bmod p}{m\bmod p}\bmod p \]
- 需要 \(p\) 为质数。
Some Tricks
2023.10
- nxt 的淫奇应用
- 只要题目牵扯到 “连通性”,大概率就是要缩点(?
- 边权仅为 \(1\) 的图,跑单源最短路,纯 bfs 的 \(O(n)\) 比 Dijkstra 的 \(O((n+m)\log n)\) 更优。【[CSP-S 2022] 假期计划】
- 可以先预处理一段的贡献,再统一做 DP 【[ZJOI2006] 物流运输】
- 输出程序空间的方法(from XSC062
Example
#include <bits/stdc++.h>
bool _bg; // 程序的最开始
using namespace std;
typedef long long ll;
int main () {
// ... Code
bool _ed; // 程序的最末尾
printf("%lf", (&_ed - &_bg) / 1024.0 / 1024.0);
return 0;
}
- 先写暴力 (dp) 再考虑优化。
- 正难则反(多用于计数类问题)【同色三角形】
- g++
考试总结
10.6 NKOI-S Round2
- 不要觉得暴力只有十几二十分就不去拿【T4】
- 数据范围并不总是提示做法,适合题目的才是最好的【T3】
- 总要找时间去码代码,不要一直呆在那里想
- 先做最有把握的题【T3】
10.14 NKOI-S Round4
- 最好每道题都输出下空间(方法见 Trick)【T2】
10.19 NKOI-S Round6
- 一道题不要卡太久【T1】
日常犯智
- Dinic 中,如果
rest
为 \(0\),直接终止循环。(真的会快很多
Dinic
int dinic (int u, int flow) {
if (u == T) return flow;
int rest = flow;
for (int i = now[u]; i && rest; i = edge[i].nxt) { //rest
now[u] = i;
int v = edge[i].v, c = edge[i].c;
if (c > 0 && d[v] == d[u] + 1) {
int k = dinic(v, min(rest, c));
if (!k) d[v] = 0;
rest -= k, edge[i].c -= k, edge[i^1].c += k;
}
}
return flow - rest;
}
-
fill()
的第二个参数应该指向末尾的下一个指针。 -
\(\large\star\) 对于 \(ax+by=\gcd(a,b)\),
Exgcd
求出的 \(x,y\),一定保证 \(x\) 最小,但不一定是正数,转为最小整数:(求逆元时一定要用)
\[p=b/\gcd(a,b),x\gets(x\%p+p)\%p \]
- Hash 时,求模数的若干次方时,\(P[0]\) 记得赋成 \(1\)。
(n>>1)+1
当然不等价于n>>1|1
……(比如n=3
就 G 了【NKOI-S R3 T2】- 一些复杂条件的
if
嵌套,或者少写一个vis
而用dis
代替,不要为了少几行代码,写可能出锅的代码【最大半连通子图 & [CSP-S 2022] 假期计划】 - 时间复杂度不能凭感觉算,\(2500\) 的 \(O(n^2)\) 也是可以过的【[CSP-S 2022] 假期计划】
- Dijkstra 的权值一定不能在从队列里面拿出来之后再更新(详见 90pts & 100pts 的代码【[SCOI2009] 最长距离】
- (from jzb) 记得考虑除数为 \(0\) 的情况,否则如果是
double
的话会出现inf
- 斜率优化注意是要 “后减前” 否则斜率算出来是负数,最小值求成最大值。