杂题题解

Wannafly挑战赛26 msc的棋盘

首先是考虑按行列建一个二分图出来,然后一个合法解一定使得这张二分图的最大流等于 \(\sum\limits_{i=1}^mb_i\)
考虑最大流-最小割定理,发现就是求所有使得整张图的最小割等于 \(\sum\limits_{i=1}^mb_i\) 的方案数。
考虑假设给出了一组 \(a_i\) 怎么判断是否合法,由于最小割一定能取到 \(\sum\limits_{i=1}^mb_i\) ,那么我们只需要看有没有其它方案花费小于这个值即可。
假设强制断掉 \(i\) 条源点到行的边, \(j\) 条列到汇点的边,那么剩下的点不连通一定会割掉 \((n-i)*(m-j)\) 条中间的边,由于是求最小割因此应当取前 i 小的 a 和前 j 小的 b 来割掉。
那么把 \(a,b\) 排序,记 \(sa,sb\) 为其前缀和,那么这张图合法的条件就是 \(\min\limits_{i,j\ge0}\{sa_i+sb_j+(n-i)*(m-j)\}\ge\sum\limits_{i=1}^mb_i\)
然后就设 \(f_{i,j,k}\) 表示当前选了前 i 小的 a 边,所有 a 边的长度不超过 j ,且和为 k 的方案数,对于每个 i 我们预处理出最小的 i 条 a 边的长度和最小值来限制转移就行了。
code


Comet OJ - Contest #14 水平竖直线段

卡空间比题目本身难.jpg
首先转化模型就是给你若干横纵线段,交点看做一条边,判断每个点是不是割点(度数小于 2 的不算)。
考虑用扫描线+主席树来进行辅助构造一个 dfs 森林,然后在建好的森林上跑 tarjan 算法, low 的更新可以遍历整棵主席树来求,复杂度 \(O(n\log n)\)
卡空间毁一生。。。
code


uoj#500. 任意基DFT

模板题调一年,没救了233。
推导差不多就是这个题吧,这么简单懒得写了
然后这题跟那题的区别就是次幂用组合数拆而不是平方数拆,其它感觉都差不多,做两遍 fft 就能过了。
然后我阶乘预处理写错了没发现调了1h
code


Comet OJ - Contest #13 「蓬莱的弹枝 -七色的弹幕-」

码力欠费.jpg
不知道为啥写个分块体都这么多锅。。。
这题应该是典型的各凭本事分块维护题。
我开了 \(K\) 块,每个块记录整体加的权值,维护一个可支持 pop 和 push 的循环队列,并且维护每个数出现的次数。
然后大力莽可以做到空间 \(O(nK)\) ,时间 \(O(n(K+\frac nK))\) 的复杂度。
code


Comet OJ - Contest #12 Substring Query

又被卡栈了,心情简单.jpg
考虑分类讨论一下几种情况:

  1. border 的长度不超过 \(\min\{l-1,n-r\}\) ,直接 kmp 做就完了。
  2. border 的长度超过 \(\min\{l-1,n-r\}\) ,那么假设是这个样子:

    发现 A 是 \(S[1,L-1]\) 的 border , B 是 \(S[L,n]\) 的 border ,且 \(2|A|+|B|<L\)
    然后离线询问,维护正反串的 border 树就能做了。
    然后我又 tm 被卡栈了,发现怎么搞都过不了之后把 dfs 改成了 bfs 才过,bfs 求 dfs 序真 tm 的鬼畜
    code

Comet OJ - Contest #10 大鱼弱智

考虑单次询问怎么做。
先二分答案 K ,那么简单移项之后可以得到合法的条件是 \(a_i-Kb_i\ge a_j-Kb_j\)
一个很简单的想法是维护 K 个 st 表,然后发现时空都炸掉。
考虑优化,由于这个 K 是一个 \([0,1000]\) 的数 \(A\) 以一个 \([0,2000]\) 之内的数 \(B\) ,那么对于每个分子 \(A\)\(\lfloor\frac AB\rfloor\) 只有 \(\sqrt A\) 种取值,可以对 \(\ge\sqrt A\) 的取值和 \(<\sqrt A\) 的分开维护。
前者如果取到说明 B 的值 \(\le\sqrt A\) ,那么我们对于每一个 \(b_i=v\) 的数以 \(v\) 为关键值维护 st 表,用来区间 \(a_i/-a_i\) 的最值,查询的时候直接查询 \(b_i=1,2...\sqrt A\) 时的最值然后 \(O(A) merge\) 即可,单次复杂度 \(O(A)\)
后者就考虑二分答案,然后 check 由于 st 表开不下可以上 zkw 线段树,单次复杂度 \(O(\log n\log A)\)
然后就跑过去了。
code


Comet OJ - Contest #10 缘木求鱼

先考虑对于单个 x 的 f(x) 怎么算,考虑对于一个 x 走到最大值处的路径。
首先假设只有最高位为 1 ,那么会一直往右走。
然后考虑整个串中至少有两个 1 的情况,对于当前的 x ,其左子树长度为 \(len1=\lfloor\frac{x+1}2\rfloor\) ,右子树长度为 \(len2=\lfloor\frac x2\rfloor\)
最大值在左子树的条件是 \(\lceil\log_2^{len1}\rceil>\lceil\log_2^{len2}\rceil\) ,画一个 01 串出来模拟发现可以发现,在触及最高的两个 1 之前,一直走右子树,触及到第二高的 1 之后一直走左子树,最后一步走右子树。
于是一个串的 f(x) 只跟其最高的两个 1 有关,设他们在第 \(p,q\)\(p>q\) (从第一位开始计数),然后 \(f(x)=2^{p+1}-2^{p-q+1}+1\)
这样可以支持 \(O(n)\) 比较两个串,考虑可能成为答案的串有哪些。

  • 串长在 \([\max\{m-1,n\},m]\) 之间。
  • 要么为 L ,要么整个串里面 1 不超过两个,即 \(x=2^p+2^q\)
  • 对于相同串长的串,满足 p 相同,那么 q 应该接近 \(\lfloor\frac p2\rfloor\)
    证明:设 \(P=2^p,Q=2^q\) ,显然 \(P\) 是常量,令 \(g(Q)=\frac{f(x)}x=\frac{2P(1-\frac1Q)+1}{P+Q}=\frac{(2P+1)Q-2P}{Q^2+PQ}\)\(g'(Q)=\frac{(2P+1)(Q^2+PQ)-(2Q+P)((2P+1)Q-2P)}{(Q^2+PQ)^2}>0\Rightarrow (2P+1)Q^2-4PQ-2P^2<0\) ,发现范围在 \(\sqrt P\) 附近。

这样枚举的串的数量降到了常数个,总复杂度 O(n)。
code


Comet OJ - Contest #9 XR-3 Unknown Mother-Goose

bitset 题加点小优化。
考虑到直接暴力枚举每个数的倍数更新复杂度有点假,而对于小于 64 的数在更新几次后会出现循环节,然后预处理优化 __builtin_popcount 的常数。
复杂度大概是 \(O(\frac {n|S|}{64}+\frac n{21})\) 的样子,然后它过了,过了就行。
code


Comet OJ - Contest #9 XR-3 Namid[A]me

又被卡栈了,心情简单.jpg
复杂度分析题...
首先考虑 \(x^x\equiv g^{ord_x*x}\mod P\) ,然后就能对一个 \(x\) \(O(1)\) 算答案。
考虑一条链上如果起点确定最多 log 段不同的与值,然后考虑合并链的复杂度是 \(O(\min(d\log)^2,n^2)\le O(nd\log)\)
于是暴力合并就行,注意不要犯 merge 加 inline 之类的傻逼操作...
code


uoj#424. 集训队作业2018 count

转化题意后发现是笛卡尔树计数。
\(F_i(x)\) 表示整棵树从根节点往下走最多走 \(i\) 次左子树的生成函数,这样要求的就是 \([x^n]F_m(x)\)
那么有转移 \(F_i(x)=F_{i-1}(x)*x*F_{i}(x)+1\Rightarrow F_i(x)=\frac1{1-xF_{i-1}(x)}\)
这里用一个 trick ,即令 \(F_i(x)=\frac{A}{B}\) ,发现 \(A,B\) 的转移可以矩乘,于是先全部转点值,矩乘之后转回去求逆即可。
code


uoj#428. 集训队作业2018 普通的计数题

题意转化比较神仙,发现进行一次操作 2 一定会去掉前面的一些操作,这样长成了一棵树。
这棵树的性质如下:

  1. 操作 1 一定是叶子结点,操作 2 一定是非叶子结点
  2. 父亲的标号比儿子标号大
  3. 如果一个点的所有儿子都是叶子,那么儿子数在集合 B 内,否则儿子数在集合 A 内

然后就可以 dp 了。
\(f_i\) 表示 i 个点树的数量(节点数>1), \(g_i\) 表示 i 个点的森林(每棵树节点数>1)的数量。
然后有如下转移:
\(f_n=[n-1\in B]+\sum\limits_{i=0}^{n-2}[i\in A]C_{n-1}^ig_{n-1-i}\)
\(g_n=\sum\limits_{i=1}^{n}C_{n-1}^{i-1}f_ig_{n-i}\)
然后分治 ntt 优化即可。
code


uoj#449. 集训队作业2018 喂鸽子

考虑 min-max 容斥: \(Ans_n=\sum\limits_{i=1}^n(-1)^{i-1}C_n^ians_i\) ,设 \(f_{i,j}\) 表示 j 粒玉米不能喂饱 i 只鸽子的概率。

\[\begin{aligned} ans_t=&\sum\limits_{i\ge1}\sum\limits_{j=0}^iC_i^j(\frac cn)^j(1-\frac cn)^{i-j}f_{t,j}\\ =&\sum\limits_{i=0}^{t(k-1)}f_{t,i}(\frac cn)^i\sum\limits_{j\ge0}C_{i+j}^j(1-\frac cn)^j\\ \sum\limits_{i\ge0}C_{i+t}^tp^i=&(\frac1{1-p})^{t+1}\\ \Rightarrow ans_t=&\frac nc\sum\limits_{i=0}^{t(k-1)}f_{t,i}\\ f_{t,i}=&[x^i](\sum\limits_{i=0}^{k-1}\frac{x^i}{i!})^t\\ (f_t(x))'=&t(f(x)-\frac{x^{k-1}}{(k-1)!})f_{t-1}(x)\\ (f_t(x))'=&t(f_t(x)-\frac{x^{k-1}}{(k-1)!}f_{t-1}(x))\\ \end{aligned} \]

然后递推即可。
code


[AGC043C] Giant Graph

首先发现一定是贪心依次选当前 \(i+j+k\) 最大的。
然后考虑一维的情况,发现可以建个 dag 出来跑出来可选的点。
但现在有三维,发现把三维叠加起来相当于是一个组合游戏,于是上 fwt 即可。
code


[AGC043D] Merge Triplets

比赛的时候 C 想错了导致没开这题,感觉亏得亿批...
想了个跟官方题解推导过程略有出入的做法。
考虑说假设现在还有 \(K\) 个序列,那么需要比较 \(K-1\) 次可以得出最小值,也就是说当 \(K>1\) 时我们没法立即知道当前局面填进序列的是哪个数。
所以考虑 \(K=1\) 时候的情况,发现这个时候这个序列的首部一定是除开它后面的数其余所有数的最大值。
换言之,我们转化一下问题。
每次可以找到当前还没有填进序列的所有数的最大值,把它和它在序列的后缀依次填入序列。
那么可以填的长度只有 \(1/2/3\) ,并且每个 \(2\) 需要跟 \(1\) 进行组合,于是我们考虑设 \(f_{i,j}\) 表示当前还有 i 个数没填,选了的 \(2\) 的数量和 \(1\) 的数量的差为 \(j\) 时的方案数然后做个 \(dp\) 即可。
code


某模拟题引出的一个小trick

\(\sum_{i=0}^nC_n^iQ^i(\sum\limits_{j=1}^ij^K)\) ,要求做到跟 \(K\) 有关的复杂度。
貌似直接按照题意模拟可以直接快速插值+多项式快速幂做到 \(O(K\log^2K)\)
upd:可以直接斯特林数做到单 log ,果然我是屑
不过我考试的时候想了一个 \(O(K^2)\) 的奇奇怪怪的做法然后由于 fix 时间不够的问题被卡常
下来之后感觉有个地方不像是我的水平能想出来的所以需要记录一下。
首先令 \(S(x)=\sum\limits_{i=1}^xi^K\) ,我们花费 \(O(K^2/K\log^2K)\) 的时间把这个多项式给插值出来。
下面令 \(K\) 等于 \(\deg(S(x))\)
然后对每一项 \(s_t\) 统计答案,发现要求的就是 \(t=0,1,2,...,K\) 的时候 \(\sum\limits_{i=0}^nQ^iC_n^ii^t\) 的值。
对这个式子略加变形,发现要求的是 \(n!Q^n\sum\limits_{i=0}^n\frac{i^t}{i!}\frac{(\frac1Q)^{n-i}}{(n-i)!}\)
然后令 \(F_t(x)=\sum\limits_{i\ge0}\frac{i^tx^i}{i!}\)
然后就只用求 \(n!Q^x[x^n](F_t(x)*e^{\frac1Qx})\)
观察 \(F\) 的转移,发现是 \(F_0(x)=e^x,F_i(x)=x(F_{i-1}(x))'\)
不妨设 \(F_t(x)=e^x*A\) ,那么 \(A\) 的转移是 \(A\leftarrow x(A+A')\)
发现我们能在 \(O(K^2)\) 的时间内递推出所有的 \(A\) ,剩下的就是要求 \(n!Q^n[x^n](A*e^{(\frac1Q+1)x})\) ,这个单次复杂度是 \(O(K)\) 的,于是就做完了。
code
好,我们尝试用这个做法来解决另外一个问题:求所有 n 个点的无向图中连通块数的 m 次方和。
考虑构造生成函数 \(G_m(x)=\sum\limits_{i\ge0}\frac{i^mx^i}{i!}\) ,根据上面的推导有 \(G_m(x)=x(G_{m-1}(x))'\)
\(G_m(x)=H_m(x)*e^x\) ,我们先递推出所有的 \(H\) ,然后把 \(F(x)\) 带入每个 \(H(x)\) 求出 \(G(x)\) 即可,其中 \(F(x)\) 是无向连通图生成函数, \(e^F\) 是无向图生成函数,复杂度为 \(O(mn\log n+m^2n)\)

code
冷静一下会发现构造的这个 \(H_m(x)\) 就是第二类斯特林数,也就是说我们一直在编的本质上就是 \(\frac{n^m}{n!}=\sum\limits_{i=0}^nS_2(m,i)*\frac1{(n-i)!}\),博主就真是个sb


某数学题

from DZYO'blog
给出 \(x_1,x_2,...,x_n\) ,令 \(x_i^{(1)}=\frac{x_i+x_{i+1}}2,i=1...n\) ,其中 \(x_{n+i}=x_i.\)
归纳地定义 \(x_i^{(k)}=\frac{x_i^{(k-1)}+x_{i+1}^{(k-1)}}2,i=1...n\) ,其中 \(x_{n+i}^{(k-1)}=x_{i}^{(k-1)},k=2,3...\)
求证 \(\forall i,\lim\limits_{x\rightarrow+\infty}x_i^{(k)}=\frac{x_1+x_2+\cdots+x_n}n\)
证明:
考虑 \(x_1,x_1,...,x_n\)\(x_S^{(T)}\) 的贡献
根据组合意义知道 \(x_{T+i}\) 的系数相当于是从 \((i,i)\) 出发,每次可以向右/下走,走到 \((T,0)\) 的方案数,于是可以列出式子 \(x_S^{(T)}*2^T=\sum\limits_{i=0}^Tx_{S+i}C_T^i\)
由于 \(x_i\) 是循环定义的,所以直接考虑 \(x_k\) 的系数,发现是 \(\sum\limits_{i=0}^T[k\equiv i\mod n]C_T^i\)
用单位根反演展开之后把 \(2^T\) 除过去即可证明 \(x_1\) ~ \(x_n\) 的系数在 \(T\rightarrow+\infty\) 的时候趋近于 \(\frac1n\)


Codeforces 1336D

考虑逆推做法。
首先假设当前 \(x\)\(a\) 个,那么如果你加入一个 \(x\) 第一维会增加 \(C_a^2\) 的贡献,显然如果 \(a>1\) 的话是能被唯一确定的。
然后假设对于一个 \(a_i\) ,如果加入一个 \(i+2\) 第二维会增加 \(a_i*a_{i+1}+a_{i+1}*a_{i+3}+a_{i+3}*a_{i+4}\) ,也就是说如果知道 \(i\) 后面四项的值就能够确定 \(a_i\) ,这样的话我们考虑询问 \(2,3,...,n-2,n,n-1,n\) ,然后可以依次确定 \(a_n,a_{n-2},a_{n-1},a_{n-3}\) ,然后倒着往回推就完事了。
code


Codeforces 1336F

对于相交的路径,考虑它们的 \(lca\) 相同/不同的情况。
如果 \(lca\) 不同可以用 \(dfs+bit\) 轻松做到单 \(\log\)
如果 \(lca\) 相同,我们先用类似处理 \(lca\) 不同时的方法处理掉这种情况:

然后剩下的一定满足 \(((x1,lca),(x2,lca))\ or\ ((y1,lca),(y2,lca))\) 中至少有一对路径有大于 1 的公共点。
然后可以考虑利用重链剖分的性质+线段树合并+启发式合并来求答案。
感觉我比较口胡,其实主要是我语文不好详细的可以去看题解或者私信博主。
code


Codeforces 1336E2

感觉就是通过观察把 \(E1\) 做法后面的 \(DP\) 改成了搜索。
\(Rank<=\lfloor\frac m2\rfloor\) 的时候直接爆搜 \(2^{Rank}\) 种线性基组合,每个被组合出来的数的贡献是 \(2^{n-Rank}\) .
现在只需要讨论 \(Rank>\lfloor\frac m2\rfloor\) 的情况。
首先考虑硬点一个 \(x\) 表示求 \(pop\_count\)\(x\) 时候的答案。
那么考虑用异或卷积来实现这么一句废话: 每个 \(pop\_count\)\(x\) 的数都会对答案有 \(2^{n-Rank}\) 的贡献。
我们设线性基能表示出的所有的数形成的集合为 \(S\) ,求出的线性基里面每个数的集合为 \(T\) ,那么我们构造数组 \(A\) 满足 \(A_i=[i\in S]\) 和数组 \(B\) 满足 \(B_i=[pop\_count(i)==x]\)
然后根据 \(iwft\) 的性质, \(0\) 处的值等于 \(\frac{\sum\limits_{i=0}^{2^m-1}fwt(A)_i*fwt(B)_i}{2^m}\)
因此我们分别考虑 \(fwt(A)\)\(fwt(B)\) 的性质:
先考虑比较简单的,假设 \(pop\_count(z)=y\) ,那么 \(fwt(B)_z=\sum\limits_{i=0}^{2^m-1}[pop\_count(i)==x](-1)^{pop\_count(i\&z)}\) ,简单组合数学一下可以得到 \(fwt(B)_z=\sum\limits_{i=0}^{x}C_y^i*C_{m-y}^{x-i}(-1)^i\) .
发现式子跟 \(z\) 没有关系,因此我们只需要统计 \(fwt(A)\) 中下标的 \(pop\_count\) 值为 \(y\) 的系数和。
然后是一个神仙玩意儿,在听 fsy 评讲观察后发现 \(A\oplus A=A\cdot 2^{Rank}\) ,这说明 \(fwt(A)_i=2^{Rank}/0\) ,由于我们考虑的是系数和,因此只需要考虑 \(fwt(A)_i=2^{Rank}\) 的位置是哪些。
观察到 \(fwt(A)_y=\sum\limits_{i=0}^{2^m-1}[i\in S](-1)^{pop\_count(i\&y)}\) ,因此满足条件的 \(y\) 一定有 \(pop\_count(y\&x)为偶数,x\in S\).
再考虑一个容易想到的结论是如果 \(pop\_count(a\&b),pop\_count(a\&c)\) 都为偶数的话,那么 \(pop\_count(a\&(b\oplus c))\) 也是偶数,因此条件等价于 \(pop\_count(y\&x)为偶数,x\in T\).
这个就比较容易了,考虑把每一位看成一个变量 \(x_i\) ,显然交换 \(x_i\) 并不影响答案,考虑对于对 \(i\) 行,我们从高到低找到第一个系数为 \(1\)\(x_j\) ,然后交换 \(x_i,x_j\) ,这样操作完之后,只看线性基构成的矩阵的前 \(Rank\) 列显然是一个单位矩阵,每行每列之间互不影响。
考虑对 \(Rank+1...m\) 列每行乱点 \(y\) 的这一位是 \(1/0\) ,显然有 \(2^{m-Rank}\) 种点法,然后假设确定了一种点法,对于每 \(i\) 行可以根据第 \(Rank+1...m\) 列的 \(1\) 的个数的奇偶性来确定 \(y\) 当前位填啥,因此可行的 \(y\) 就只有这乱点 \(2^{m-Rank}\) 种,直接搜出每种情况加到系数上就行。
code


loj#3228. 「USACO 2019.12 Platinum」Tree Depth

考虑两个东西:

  1. 逆序对数 \(dp\) 的另一种理解,考虑每次在末尾/开头加一个数,然后讨论它跟之前的数的大小关系,第 \(i\) 次插入可以增加 \(0\) ~ \(i-1\) 个逆序对,注意到使用这个意义的话我们的序列一定是连续的且每次可以在头/尾转移.
  2. 关于求笛卡尔树的深度,可以转化成统计每个位置作为该位置祖先的方案数.

利用第二条可以直接硬点 \(j\) 作为 \(i\) 的祖先求方案数,然后转移的条件是 \(j\) 处的值一定是区间 \([i,j]\) 中的最小值,相当于把转移的生成函数从 \(\frac{1-x^j}{1-x}\) 换成 \(x^{j-i}/1\)用脚维护一下就行了.
code

posted @ 2020-03-15 12:58  soroboruo  阅读(503)  评论(0编辑  收藏  举报