2025 备战 NOIP 记录
DP
CF1928E(*2300)
先 \(s\gets \frac{s-n\times(x\bmod y)}{y},x\gets \lfloor\frac{x}{y}\rfloor\),变成一个形如 \(x,x+1\dots x+k_1,0,1,\dots k_2,0,1,\dots\) 的数列。
枚举 \(k_1\),于是形式统一。因为后面的一堆东西没什么性质能够直接构造,考虑 DP 求解。
但是直接 DP 肯定会炸,于是试图降维。
注意到如果长度为 \(L\),和为 \(s\) 时能够给出构造,则长度为 \(L+1\),和为 \(s\) 时也能通过加一个 \(0\) 得到方案,于是设 \(dp_i\) 表示和为 \(i\) 时的最小长度,因为可能的转移只有 \(O(\sqrt s)\) 种所以时间复杂度 \(n\sqrt s\)。
CF1943D(D1*2400,D2*2800)
如果 \(l\le r\),那么就是积木大赛,考虑使用类似方法从差分数组考虑。
设差分数组为 \(d_{1\dots n}\),每次操作形如 \(d_l\gets d_l-1,d_{r+1}\gets d_{r+1}+1\),则 \(a_{1\dots n}\) 是好数组当且仅当 \(\forall d_i<0,\sum\limits_{j\le i-1} d_j\ge -d_i\),还原到 \(a\) 上就是 \(\forall i\in[1,n],a_{i-1}+a_{i+1}\ge a_i\),其中 \(a_0=a_{n+1}=0\)。
于是可以直接设 \(dp_{i,j,k}\) 表示前 \(i\) 个数满足条件,且 \(a_i=j,a_{i-1}=k\) 的方案数,可以使用前缀和做到 \(O(n^3)\),当然没还原到 \(a\) 也可以类似地 DP 做到 \(O(n^3)\)。
但是这样还是太浪费了,因为对于任意的 \(a\),显然不可能有相邻的两个 \(i\) 不满足条件,于是可以直接设 \(dp_{i,j}\) 表示前 \(i\) 个数满足条件,且 \(a_i=j\) 的方案数,容斥掉 \(a_{i-2}+a_{i}\le a_{i-1}\) 的情况即可 \(O(n^2)\),不能直接从 \(i-2\) 转移是因为可能存在 \(a_{i-2}\ge a_{i-3}\),有后效性。
CF1620G(*2400)
容斥板子。
令 \(s_i\) 为 \(s_{i,a}\) 个 \(a\),\(s_{i,b}\) 个 \(b\)……构成,显然一个字符串的子串个数为 \((c_{i,a}+1)(c_{i,b}+1)\dots\),\(s_1,s_2\dots s_k\) 共同的字串个数为 \((\min\limits_i c_{i,a}+1)(\min\limits_i c_{i,b}+1)\dots\),因为每个集合的容斥系数固定,所以高维前缀和即可。
CF1322D(*2800)
感觉不像*2800啊?
显然正着加人状态数会爆,于是考虑倒着加,但是相同的等级可能会打出很多情况(比如 \(1\ 1\ 1\ 1\ 1\) 会打成 \(1\ 3\)),怎么办呢?
考虑直接记 \(dp_{x,i,j}\) 表示 \(x\) 后面的人中最大的为 \(i\),有 \(j\) 个的方案数,统一转移 \(dp_{x,i+1,\lfloor\frac{j}{2}\rfloor}\gets dp_{x,i,j}+\lfloor\frac{j}{2}\rfloor\times c_{i+1}\),容易发现这样是对的。
CF1806D(*2500)
喜报:\(a_{p_i}\) 看成了 \(a_i\),这样是做不了的(如果能做请告诉我,谢谢!)
考虑什么时候会合并 \(1\) 所在的连通块,发现是 \(p_i=\text{mex}_{1\le j\lt i} p_j\) 时,此时若 \(a_i=0\) 则能贡献 \(1\) 的答案(加入一条 \(1\) 的入边),否则之后都不能贡献答案(\(1\) 有出边)。
于是分别维护 \(dp_0,dp_1,dp_2\) 表示当前还能贡献的排列的个数,当前还能贡献的排列的总贡献,当前不能贡献的排列的总贡献。
- 若 \(a_i=0\),有 \(dp_0\gets dp_0\times i,dp_1\gets dp_1\times i+dp_0,dp_2\gets dp_2\times i\)
- 若 \(a_i=1\),有 \(dp_0\gets dp_0\times (i-1),dp_1\gets dp_1\times(i-1),dp_2\gets dp_2\times i+dp_1\)
时间复杂度线性。
还有一个只考虑能贡献答案的点,用 \(f_i\) 表示到 \(i\),\(1\sim i−1\) 都在 \(i\) 之前,且目前根为 \(1\) 的方案数,然后用组合数计算贡献的做法。
P11316
喜报:看成无标号了想了半天。
直接做是可以做的,考虑对 \(\bmod m\) 相同的数一起做匹配,设 \(dp_{i,j}\) 表示当前考虑到余数位 \(0\sim i\),匹配了 \(j\) 个的方案数,转移时枚举向前匹配了多少个数,时间复杂度是正确的。
也可以容斥,对 \(\bmod m=i\) 的部分计算 \(w_i\) 表示选出 \(i\) 组的方案数,背包即可,时间复杂度也是一样的,要注意转移的上界。
组合数学
其它
CF1054E(*2400)
感觉这个 \(3L\) 的限制就是在告诉你要把 \(0\) 和 \(1\) 分别集中起来再重新分配啊。
-
先将所有 \(0\) 放到第一行,所有 \(1\) 放到第二行,这里要注意如果要放到同一行的需要放到一个同行不同的列而不是不放。
-
然后操作前两行使得 \(0/1\) 的个数符合答案的要求。
-
类似于第一步地放回去即可。
CF1658E(*2500)
显然,你需要按数值从大到小递推胜方。
发现每次转移需要将所有和 \((x,y)\) 间曼哈顿距离大于 \(k\) 的点覆盖为 \(1\),先转切比雪夫距离变成矩形外操作,然后分别对 \(x\) 和 \(y\) 维护当前还没删掉的左右边界即可。
闲话:开始时开了 set 被卡常了。
CF350D(*2400)
思路都会,分享一个好写的做法。
考虑使用 \(ax+by=c\) 形式存储直线,显然 \((x_1,y_1)\) 和 \((x_2,y_2)\) 确定的直线有方程 \((y_2-y_1)x+(x_1-x_2)y=c\),其中 \(c\) 容易根据点坐标计算得出,做垂直相当于 \(a\gets -b,b\gets a\),然后同除最大公因数再处理正负即可。
CF754E(*2600)
\(O(n^4)\) 是显然的,考虑怎么优化。
在 OI 中比较普及的字符串科技似乎都不会处理通配符,怎么办呢?
一种方法是多项式,但是我不会。
另一种方法是用 bitset 除掉一个 \(\omega\),发现可以通过预处理在每个位置取每个字母是否能匹配每个模式串做到,跑得飞快。
CF283D(*2400)
考虑怎么判断 \((x,y)\) 是否 cool。
令起始的数为 \(a\),则有 \(\frac{(2a+y)y}{2}=x\)
于是发现若 \(y\) 是奇数,则 \(x=2(2k+1)y(k\in \text{Z})\)(对不起我不知道 MathjJax 怎么渲染双线字母),否则 \(x=ky(k\in \text{Z})\)
于是直接 \(O(n^2)\)DP 即可。

浙公网安备 33010602011771号