一些省选题

BJOI2019

loj #3089. 「BJOI2019」奥术神杖

看见乘法的贡献就应该考虑取对数,之后变成\(\frac{1}{c}\sum \ln v_i\).

求这个式子的最值可以考虑分数规划,即二分\(mid\)后check\(\frac{1}{c}\sum \ln v_i>mid\)

整理后得\(\sum(\ln v_i-mid)>0\),故可以将每个串的长度记作\(\ln v_i-mid\),之后就是一个经典的在AC自动机上dp的过程了,注意记录转移以输出方案。

code

loj #3090. 「BJOI2019」勘破神机

先考虑\(m=2\)的case,发现填满一个\(2\times n\)的方格的方案就是\(fib_{n+1}\),其中\(fib_i\)表示斐波那契数列的第\(i\)项。

答案\(=\frac{1}{r-l+1}\sum_{i=l+1}^{r+1}\dbinom{fib_i}{k}\),和这个题是一样的。

接下来考虑\(m=3\)的case。依然是先算填满一个\(3\times n\)的方阵的方案数\(g_n\),由于\(n\)必然为偶数,于是可以考虑其为\(3\times (n\times 2)\)的方案数。递推的话可以考虑上一个不经过分界线的矩阵大小,若其为\(2\)则有\(3\)种,否则则为\(2\)种。故可得到递推式\(g_n=\sum_{i=1}^{n-2}2g_i+3g_{n-1}\).将\(g_{n+1}\)\(g_n\)做差可得\(g_{n+1}=4g_n-g_{n-1}\),边界条件\(g_0=1,g_1=3\).利用特征根法解得通项式如下:

\[g_n=\frac{3+\sqrt 3}{6}(2+\sqrt 3)^n+\frac{3-\sqrt 3}{6}(2-\sqrt 3)^n \]

剩下的和\(m=2\)的一致。

code

loj #3092. 「BJOI2019」排兵布阵

分组背包即可,跑得飞快。

code

loj #3093. 「BJOI2019」光线

\(f_i\)为1号镜子入射的光线从\(i\)号镜子向下射出的量,\(g_i\)表示1号镜子入射的光线从\(i\)号镜子向上反射的量,转移有:

\[f_i=a_if_{i-1}+b_ig_{i+1}\\ g_i=b_if_{i-1}+a_ig_{i+1} \]

注意由于\(g_{n+1}=0\),所以有\(f_n=a_nf_{n-1},g_n=b_nf_{n-1}\).

\(X_i=\frac{f_i}{f_{i-1}},Y_i=\frac{g_i}{f_{i-1}}\),那么转移式可以写成:

\[X_i=a_i+b_iY_{i+1}X_i\\ Y_i=a_i+a_iY_{i+1}X_i \]

由于\(X_n,Y_n\)已知,所以可以倒推求出\(X_i\),再求出\(f_n\)即可。

当然还有一个做法是不显式的设出\(X,Y\),注意到由于\(f_n,g_n\)分别可以被\(f_{n-1},g_{n-1}\)表示出来,再往前推既可以发现\(f_i,g_i\)分别可以被\(f_{i-1},g_{i-1}\)表示。最后由\(f_0=1\)再往后乘一遍系数即可。

code

loj #3094. 「BJOI2019」删数

对于一个序列\(a\)首先考虑怎样才能使它被一次删干净。由于长度为\(n\),所以\(a\)中必有元素\(n\),假设有\(k_1\)个。为了能继续删,序列\(a\)中必有元素\(n-k_1\),假设有\(k_2\)个,以此类推。

用一个形象化的比喻来解释最后的结论:记\(b_i=\sum_{j=1}^n [a_j=i]\),考虑一根数轴上有一些柱子,点\(i\)的柱子高度为\(b_i\),那么最少修改次数等于将\([1,n]\)中的所有柱子向右推倒后未被覆盖的整点个数。

考虑用线段树维护这个过程,每个节点维护当前区间的最小值,最小值出现次数和答案,只有在最小值为0时它的次数才会被记入答案中。对于修改,单点修改直接做,整体加减的话可以记录原点\(0\)的位置,每次直接移动\(0\)的位置,再修改由此离开或进入\([1,n]\)的柱子的贡献,此时需要将下标整体加上一个较大的数。

code

BJOI2018

loj #2491. 「BJOI2018」求和

注意到\(k\)很小,于是可以对所有\(k\)预处理出每个点深度的\(k\)次幂,再用树链剖分查询即可。

code

loj #2492. 「BJOI2018」二进制

结论五分钟,实现两小时

假设某个区间有\(m\)\(0\)\(n\)\(1\),那么问题等价于从集合\(\{2^0,2^1,\cdots,2^{n+m-1}\}\)中选出\(n\)个数使其和为3的倍数。

\(n=1\)时显然不成立。\(n\)为偶数时注意到\(3|2^{2k}+2^{2k+1}\)\(k\in N\)均成立,故此时一定可行。\(n\)\(>1\)的奇数时,我们可以先拿\(3\)个奇数出来选\(2^0,2^2,2^4\),剩下的数再和\(n\)为偶数的方案一样选即可。注意到此时我们需要两个\(0\)\(2^1\)\(2^3\),那么当前区间不合法的条件就很明显了:

  • \(n=1\)

  • \(n=2k+1,m<2(k\in N_{+})\)

注意到两个条件是或的关系,于是我们可以强制第一个条件满足\(m\geq 2\).

考虑用线段树维护这个东西,记\(dl/r[i][j]\)表示子区间包含当前区间左/右端点,且子区间的\(0\)\(i\)个,子区间内\(1\)的个数\(\bmod\ 2\)\(j\)的子区间数量(它被用来统计第二个条件的贡献)。\(fl/r[i][j]\)表示子区间包含当前区间的左/右端点,且子区间内有\(0/1/\geq 2\)\(0\),\(1\)个1的子区间数(用来处理第一个条件的贡献),\(c0/c1\)表示区间内\(0/1\)的个数,\(l0/r0\)表示从左端点/右端点出发的极长\(0\)段的长度(这两个是方便维护\(dl/r,fl/r\)的)。具体的pushup由于细节繁多建议直接看代码。

code

loj #2512. 「BJOI2018」链上二次求和

\(s_i\)\(a_i\)的前缀和,\(ss_i\)\(s_i\)的前缀和。二次求和肯定要写两次前缀和啊

对于一个询问\([l,r]\),把它的答案写出来:

\[\begin{aligned} &\sum_{i=l}^r\sum_{j=i}^n s_j-s_{j-i}\\ =& \sum_{i=l}^r(\sum_{j=i}^n s_j-\sum_{j=0}^{n-i} s_j) \\ =& \sum_{i=1}^r(ss_n-ss_{i-1}-ss_{n-i})\\ =&(r-l+1)ss_n-\sum_{i=l-1}^{r-1}ss_i-\sum_{i=n-r}^{n-l}ss_i \end{aligned} \]

考虑如何动态维护\(ss_i\),这样的话对每次询问可以直接查\([1,n],[l-1,r-1],[n-r,n-l]\),然后减一减得到答案。

对于一个修改\((l,r,v)\),对\(\forall i\in[l,r]\),它的影响是\(\frac{(i-l+1)(i-l+2)}{2}v\); 而对\(\forall i\in(r,n]\),记\(len=r-l+1\),则贡献为\((\frac{len(len+1)}{2}+len(i-r))v\).

注意到上面的所有贡献都可以看成是关于\(i\)的二次函数,于是可以在build的时候预处理出\(i^0,i^1,i^2\),每次修改直接传入各次项前的系数即可。具体实现可参考代码。

code

loj #2513. 「BJOI2018」治疗之雨

连续两年高妙消元?

\(f_i\)表示当前血量为\(i\),变成\(0\)的期望次数。则有:

\[f_i=1+\sum_{j=1}^{\min(i+1,n)} A_{i,j}f_j \]

其中\(A_{i,j}\)为血量由\(i\)变为\(j\)的概率,经过简单的分类讨论可以得到

\[A_{i,j}= \begin{cases} B_{i-j} & i=n,j\leq n\\ 0 & i=n,j=n+1\\ \frac{1}{m+1}B_0 & i<n,j=i+1\\ \frac{1}{m+1}B_{x+1-y}+\frac{m}{m+1}B_{x-y} &i<n,j\neq i+1 \end{cases} \]

其中\(B_i\)表示在\(k\)次操作中恰好选到某个特定点\(i\)次的概率,则有:

\[ B_i=\frac{1}{(m+1)^k}{k\choose i}m^{k-i} \]

\(f\),由于\(i\)可能由比它大的数转移过来,所以我们需要高斯消元,但是显然时间限制不允许我们这么做。

\(f_i\)的转移变形后得到:

\[f_{i+1}=\frac{f_i-1-\sum_{j=1}^jA_{i,j}f_j}{A_{i,i+1}}(i<n) \]

于是\(f_i\)可以由\(f_{i-1}\)得到,我们将\(f_1\)看做主元,可以表示出\(f_{2...n}\).

但是对\(f_n\)的转移,由于不存在\(f_{n+1}\)所以上面的变形不成立,但是我们直接利用这个转移建立起\(f_n\)\(f_1\)的第二个等量关系,之后解方程得到\(f_1\)。注意特判一下\(m=0\)\(k=0\)的情况。

code

SDOI2019

loj #3110. 「SDOI2019」快速查询

维护一些全局tag:加法add,乘法mul,赋值all以及最近的一次全局赋值时间lstall. 再对有单点赋值的位置记录一下上一次赋的值和时间。单点询问的时候比较一下全局时间和单点时间的先后。询问和的话在修改的时候顺便维护一下即可。

code

loj #3111. 「SDOI2019」染色

一眼有一个没分的dp思路:记\(f_{i,j,k}\)表示前\(i\)列已经填完,第\(i\)列的颜色为\(j,k\)的方案数。

考虑压缩状态,记\(g_{i,j}\)表示前\(i\)列,第\(i\)列新填的颜色是\(j\)的方案数。当第\(i\)列被填满时,考虑记录下面位置的颜色。那么问题变成出列一列都没有颜色的情况。注意到我们可以将这样的连续的几列放在一起处理,并且这些列的情况只与开头和结尾的两个非全零列有关,大致有以下几种:

\(1.\begin{bmatrix} a & 0 & \cdots & 0 & b\\ c & 0 & \cdots & 0 & d \\ \end{bmatrix}\)

\(2.\begin{bmatrix} a & 0 & \cdots & 0 & b\\ b & 0 & \cdots & 0 & d \\ \end{bmatrix}\)
\(\begin{bmatrix} a & 0 & \cdots & 0 & c\\ c & 0 & \cdots & 0 & d \\ \end{bmatrix}\)(两者等价)

\(3.\begin{bmatrix} a & 0 & \cdots & 0 & a\\ c & 0 & \cdots & 0 & d \\ \end{bmatrix}\)
\(\begin{bmatrix} a & 0 & \cdots & 0 & b\\ c & 0 & \cdots & 0 & c \\ \end{bmatrix}\)(两者等价)

\(4.\begin{bmatrix} a & 0 & \cdots & 0 & a\\ b & 0 & \cdots & 0 & b \\ \end{bmatrix}\)

\(5.\begin{bmatrix} a & 0 & \cdots & 0 & b\\ b & 0 & \cdots & 0 & a \\ \end{bmatrix}\)

\(f_{i,j}\)表示有\(i\)\(0\),其中首尾两列的情况为\(j\)的方案数(注意这个状态中我们只确定了首尾两列的相等情况,而没有确定具体的数是什么)

预处理出\(f\),之后对每一对极长连续的全零列转移,暴力\(O(nc)\)的转移可以得到96pts. 代码有亿点细节。

写完96pts的代码后发现我们每次对\(g\)的操作和上一题是相同的,于是可以把前一题的代码蒯过来再改一下。这里笔者由于笔者比较懒只有96pts的代码。

code(96pts)

loj #3112. 「SDOI2019」世界地图

对于询问\([l,r]\),考虑将\([1,l-1]\)\([r+1,n]\)的MST合并.即需要预处理所有前缀和后缀的MST。

这里只考虑前缀的MST,后缀的是类似情况。一个比较显然的思路是由\([1,l-1]\)推出\([1,l]\)。考虑一条新的边\((u,v,w)\)在何时会替代原MST中的边:在原MST中\(u,v\)连通且两点间路径的最大权值\(>w\).

\([1.l]\)中第一列点和最后一列点为关键点,\(pre_l\)为随着\(l\)的增大可能会被删去的边,根据kruskal的过程不难发现加入边\((u,v)\)等价于将它们的祖先连起来,所以\(pre_l\)的边的端点可以看成是关键点。所以每次向后拓展时只需要考虑\(pre_l\)与新加的边。

再考虑合并,发现我们依然可以只关注关键点的连边,于是可以将\(pre_{l-1}\)\(suf_{r+1}\)如上面一样的合并起来,具体合并过程可见代码。

code

loj #3113. 「SDOI2019」热闹的聚会与尴尬的聚会

注意到第二问这个求独立集是个经典的NPC问题,所以一个直观的想法是让\(q\)尽量小,也就是要让\(p\)尽量大。

那么有一个这样的贪心思路:每次删去当前图中度数最小的点(记作这一次删除的源点),并删去其相邻的点。每次删点时删去的点的度数最大值即为\(p\),所有删去的点在一起则构成第二问的独立集。

考虑这样得到的独立集的大小,由于每个被删去的源点在被删去时的度数\(\leq p\),所以每次删去的点的总数\(\leq p+1\),所以\(q\geq \lfloor\frac{n}{p+1}\rfloor\),合法性得证

code

联合省选2020

以下按照个人认为的难度顺序排序

Day1

loj#3305. 「联合省选 2020 B」卡牌游戏

\(s_i=\sum_{j=1}^i a_j\),由于每个\(s_i\)至多产生1次贡献,故答案\(=\sum_{i=2}^n\max(s_i,0)\).

code

loj#3306. 「联合省选 2020 B」消息传递

建出点分树,对每个点记录下它在点分树上的祖先到这个点的距离(这个可以在建立点分树的时候通过dfs当前分治重心所管理的子树得到),同时在点分树上对每个点维护其子树中的点到这个点的距离的桶。询问时直接在点分树上暴力跳父亲,然后对着桶查一下即可。

code

loj#3300. 「联合省选 2020 A」组合数问题

主要思路是将后面的\(\sum x^k\dbinom{n}{k}\)分离出来,再用二项式定理合起来即可。

\[\begin{aligned} &\sum_{k=0}^nf(k)x^k\dbinom{n}{k}\\ =&\sum_{i=0}^ma_i\sum_{k=0}^nk^ix^k\dbinom{n}{k}\\ =&\sum_{i=0}^ma_i\sum_{k=0}^nx^k\dbinom{n}{k}\sum_{j=0}^iS(i,j)k^{\underline{j}}\\ =&\sum_{i=0}^ma_i\sum_{j=0}^iS(i,j)\sum_{k=0}^nx^k\frac{n!}{k!(n-k)!}\frac{k!}{(k-j)!}\\ =&\sum_{i=0}^ma_i\sum_{j=0}^iS(i,j)n^{\underline{j}}\sum_{k=0}^nx^k\dbinom{n-j}{k-j}\\ =&\sum_{i=0}^ma_i\sum_{j=0}^iS(i,j)n^{\underline{j}}\sum_{k=0}^{n-j}x^{k+j}\dbinom{n-j}{k}\\ =&\sum_{i=0}^ma_i\sum_{j=0}^iS(i,j)n^{\underline{j}}x^j(x+1)^{n-j} \end{aligned} \]

其中\(S(i,j)\)表示第二类斯特林数。

预处理一堆东西之后就可以\(O(m^2)\)了。

code

loj#3299. 「联合省选 2020 A | B」冰火战士

记冰系战士和火系战士在温度\(i\)时上场战士的能量和分别为\(S_{0i},S_{1i}\),那么问题就是求最大的\(i\)使\(\min(S_{0i},S_{1i})\)的最大。

\(j\)为最小的\(i\)使\(S_{0i}> S_{1i}\),那么在\(i\in[1,j-1]\)时,\(\min(S_{0i},S_{1i})=S_{0i}\),此时\(j-1\)是最优解。在\(i\in[j,n]\)时,\(\min(S_{0i},S_{1i})=S_{1i}\),为了让这个值最大,需要找到一个最大的\(p\)使\(S_{1p}=S_{1j}\).

这两个操作都可以在线段树上二分实现,时间复杂度为\(O(n\log n)\)

code

posted @ 2020-06-08 21:47  EncodeTalker  阅读(127)  评论(0编辑  收藏