Cry_For_theMoon  

1. Figures

注意到存在度数限制所以考虑 prufer 序列。

考虑生成函数,即考虑单个元素 \(i\),若在 prufer 序列出现 \(k\) 次则方案数是 \(d_i^{\underline{k+1} }\)(这里不是组合数,因为孔是可区分的)。

碰到这类多个元素的合并问题常用 egf:即设 \(F_{i}(z)=\sum\limits_{k= 0}^{d_i-1}\frac{d_i^{\underline{k+1} }}{k!}z^k\),然后有 \(F(z)=\prod_{i=1}^{n}F_i(z)\),则 \((n-2)![z^{n-2}]F(z)\) 即为答案。

观察到 \(F_i(z)\) 的系数其实极为接近组合数。根据 \(x^{\underline{k}}=x(x-1)^{\underline{k-1}}\) 可以得到 \(F_i(z)=d_i(z+1)^{d_i-1}\)

所以不妨设 \(F_i(z)=(z+1)^{d_i-1}\)\(F(z)\) 依旧是它们的卷积结果。则答案为 \((\prod_{i=1}^{n}d_i)(n-2)![z^{n-2}]F(z)\)

\(F(z)\) 实质上是 \((z+1)^{s}\),这里 \(s=\sum_{i=1}^{n}(d_i-1)\)

所以 \([z^{n-2}]F(z)=\dbinom{s}{n-2}\)

所以 \(ans=(\prod_{i=1}^{n}d_i)(n-2)!\dbinom{s}{n-2}\)

观察到 \(s\lt n-2\) 的时候答案为 \(0\),否则 \(\dbinom{s}{n-2}=\frac{s^{\underline{n-2}}}{(n-2)!}\),所以答案化简为 \(s^{\underline{n-2}}\times \prod_{i=1}^{n}d_i\)

时间复杂度 \(O(n)\)

记录

2. Neq Neq

容易发现如果 \(a_{i}=a_{i+1}\) 则可以把序列在此处分段。所以我们仅用考虑没有两个相邻数相等的情况。

这种情况是友好的,因为我们至少在第一步总能消去一个数。但是我们发现并不总是这样:\(\text{12121212}\) 就是反例。

容易证明只出现两种数字的时候形如 \(\text{121}\) 是唯一友好的(友好指最后可以把除了两边端点的以外的都消去)。而似乎只要有三种不同数字就一定是友好的。

证明分为两部分:1. 证明此时总能找到 \(i\) 使得 \(a_i,a_{i+1},a_{i+2}\) 互不相同。尝试构造不满足这样的串,发现只能是 \(\text{121212}\) 类型的。所以此时若三种字符都出现超过一次,我们找这个 \(i\) 消去即可。

  1. 当有一个字符只出现一次的时候,不妨设它在中间,则两边都形如 \(\text{abababab...c}\),由于 \(c\) 不再出现,所以左边必能消尽,对于右边同理,则最后消去 \(c\) 即可。而 \(c\) 在两侧的情况同理。

然后简单 dp 即可。

记录

3. Mark and the Online Exam

考虑如果初始询问一次,则之后的操作实质上变成了给出一个子集去询问匹配个数。

另外观察到这个上界略大于 \(\frac{2}{3}\),这启发我们对三个数去寻找两次询问的做法。

考虑 \(i,i+1,i+2\) 三个位置。询问 \(i,i+1,i+2\) 一次,询问 \(i,i+1\) 一次。当且仅当 \(i\)\(i+1\) 不同的时候我们不能确定做法。

牛逼的是考虑基于 \(\text{TFTFTF...}\) 这个串去询问 \(i,i+1,i+2\),基于 \(\text{TTTTT...}\) 这个串去询问 \(i,i+1\),则 \(i\)\(i+1\) 不同的四种情况可以被唯一确定。

记录

4. DFS Trees

众所周知最小生成树边权构成的多重集唯一。本题由于是排列所以这个结论等价于最小生成树唯一。

所以变成了问以某个点为根的 dfs 树是否走的都是一个最小生成树的边。最小生成树的特性使得非树边的边权一定合法(非树边 \((u,v)\) 一定大于 \(u-v\) 上边权最小的那个)。所以我们只要让横叉边不出现即可。(因为 dfs 树中不存在横叉边,只存在树边以及返祖边。)

\(1\) 为根 dfs 最小生成树,我们将看到,每条非树边会对答案造成一定限制。

  • 横叉边 \((u,v)\),则只有 \(subtree(u),subtree(v)\) (包括 \(u,v\))可以作为根。

  • 返祖边 \((u,v)(depth_u\gt depth_v)\),则只有 \(subtree(u)\),以及 \(Tree-subtree(v)\)(包括 \(u,v\))可以作为根。

两种限制本质上都可以看作子树加/减。可以 dfs 序上用 bit 维护。但是因为是离线所以直接树上差分打 tag 即可。

时间复杂度 \(O(n\log n)\)

记录

5. Partial Virtual Trees

注意到题目等价于给除了点 \(1\) 以外的所有点打tag:tag即为在哪次操作中第一次被删除。

\(max(u)\)\(u\) 子树内的最大 tag,则必须满足 \(u\)\(tag\) 大于等于子树中,\(max(v)\) 次大的值(否则说明 \(u\) 删除的时候还有至少两个子树有点,这样 \(u\) 就不能删除)。

有了这个性质以后尝试 dp:设 \(f(u,k)\) 是子树 \(u\),标号范围钦定在 \([1,k]\) 的方案数。

发现这样不好转移,不妨设 \(f(u,k)\) 为标号钦定在 \([1,k]\) 且强制让 \(max(u)=k\) 的方案数。这样我们可以在 \(n^3\) 的时间内计算出所有的 \(f\)。具体而言:观察到只有两种情况:

  • \(tag_u=k\),则 \(f(u,k)=\prod_{v}f(v,k'\le k)\)

  • \(tag_u\lt k\),设其为 \(a\),则 \(f(u,k)\) 会加上 \(\sum_{v_1}f(v_1,k)\prod_{v\neq v_k}f(v,k'\le a)\)

注意到 \(f(v,k'\le k)\) 这种东西可以用前缀和预处理,设为 \(g(v,k)\)。然后第一种情况就变成 \(O(n^2)\) 的了。但是第二种情况要枚举 \(v_1\),还是太慢了。注意到我们把 \(g(v,a)\) 的乘积预处理出来设为 \(mult\),则实际上是这样一个贡献过程:\(mult(a)\times g(v_1,a)^{-1}\times dp(v_1,b)\rightarrow dp(u,b)\),这里只要 \(a\lt b\) 都会产生贡献。所以我们直接枚举 \(b\),然后此时把 \(mult(a)\times g(v_1,a)^{-1}\) 再求一下前缀和即可。由于有逆元的缘故所以复杂度为 \(O(n^2 \log n)\),若实现不精细依旧不能通过。比较极限的手法是把 \(mult(a)\) 拆成前后缀两段,这样直接把前后缀两段相乘即可,就不用求逆元了,这个做法是严格 \(O(n^2)\) 的且不依赖模数是质数的限制。

此时依旧没有得到答案:因为题目告诉我们,\(1\sim k\) 必须在 \(tag\) 里都出现。我们现在求的 \(F(k)\) 只保证了最大 \(tag=k\) 一定出现,而 \(\lt k\) 的值不一定出现。

\(G(k)\)\(1\sim k\) 都出现的标号方案数,则有:

\[F(i)=\sum_{j=1}^{i}\dbinom{i-1}{j-1}G(j) \]

观察到这个形式非常接近二项式反演。设法让组合数变成 \(\dbinom{i}{j}\),不难发现:

\[F(i+1)=\sum_{j=0}^{i}\dbinom{i}{j}G(j+1) \]

\(f(i)=F(i+1)\)\(g(i)=G(i+1)\) 进行替换,然后得到:

\[f(i)=\sum_{j=0}^{i}\dbinom{i}{j}g(j) \]

这就是标准的二项式反演了:

\[g(i)=\sum_{j=0}^{i}(-1)^{i-j}\dbinom{i}{j}f(j) \]

\(O(n^2)\) 的时间内求出了所有的 \(g\),也就等于求出了所有的 \(G\),即所有答案。

记录

6. AND OR Equation

\(i+j=i\and j+i\or j\) 可以从集合角度加以出发理解。然后有 \(f(2^i)+f(2^j)=f(2^{i}+2^{j})+f(0)\)。如果两边同时减去 \(2f(0)\) 就会发现一个极其优美的 \(g\) 存在:\(g(2^i)+g(2^j)=g(2^{i+j})\)

所以如果确定了 \(f(0),g(1),g(2),...,g(2^{n-1})\) 我们就唯一确定了整个序列,这 \(n+1\) 个数里 \(f(0)\) 是特殊的啊。

注意到把 \(f(mask)\) 进行二进制分解,则实质上有:\(f(mask)=\sum_{i\in mask}g(i)+g(0)\) 啊。

但是 \(g\) 的取值是整数域。为了让 \(0\le f\le k\) 的目标成立,显然我们只研究 \(f\) 的最小值和最大值。即设 \(s_1\)\(g(1)\sim g(2^{n-1})\) 里全体负数和,而 \(s_2\) 是全体正数和,则有 \(g(0)+s1\ge 0\) 以及 \(g(0)+s2\le k\),那么贡献是 \(\max\{0,k+1-g(0)-(s2-s1)\}\)。而 \(s2-s1\) 就是 \(g(1)\sim g(2^{n-1})\) 的绝对值的和啊。

所以我们大概需要确定符号(那么这里就要特殊考虑 \(0\)),但是还有一个问题是那个 \((k+1)-sum\) 的系数存在。一个套路是此时再加两个非负变量进去,这样如果前面余下 \(a\) 后面就会有 \(a+1\) 种选择,最后特判后面两个都填 \(0\) 这种多判的选择就行了。

然后可以推出式子:\(ans=\sum_{i=0}^{n}2^{i}\dbinom{n}{i}\dbinom{k+1}{i+1}\)

另外还有一种生成函数出发的推法:

万物皆可生成函数啊,一个数如果最后绝对值取了正数贡献为 \(2\),否则为 \(1\),否则有生成函数 \(f(z)=1+2z+2z^2+...+2z^n+...=\frac{1+z}{1-z}\)\(n\) 个卷起来就是 \(F(z)=(\frac{1+z}{1-z})^n\)。然后考虑 \([z^a]F(z)\) 的贡献是 \((k+1-a)\),如果是组合角度,则我们很难想到上面特殊的插板法;从生成函数角度来看,由于 \(a+k+1-a\) 恒为 \(k+1\),这无非就是加了一个卷积进去:求 \([z^{k+1}]F(z)G(z)\),其中 \(G(z)=z+2z^2+...+nz^n+...=\frac{z}{(1-z)^2}\),所以求的是 \([z^{k+1}]\frac{z\times (1+z)^n}{(1-z)^{n+2}}\),分子分母都可以用二项式定理展开,最后分别得到:\(\sum_{i=0}^{\infty}\dbinom{n}{i-1}z_i\) 以及 \(\sum_{i=0}^{\infty}\dbinom{n+i+1}{i}z^i\),对其求第 \(k+1\) 项系数,即为:\(\sum_{i=0}^{n}\dbinom{n}{i}\dbinom{k+n-i+1}{k-i}=\sum_{i=0}^{n}\dbinom{n}{i}\dbinom{k+n-i+1}{n+1}\)

记录

7. Colorfulness

这下真的变纯纯的 GF 了。

首先一个容易想到的转化是:我们计数 \(p_i\),其中 \(p_i\) 是恰好有 \(k\) 个相邻不同颜色的排列数。通过 \(p_i\)\(f\)(这一步求法是一个类似科技的东西,是一个较硬伤的东西啊。)我们先假设这总是可行的。

我们发现直接求 \(p\) 仍然存在一定困难。首先不妨转成求相邻的相同颜色个数,这显然好做。发现一个诱人的想法:对每种颜色分别求出某些东西,将其的 \(egf\) 直接卷起来即可。容易发现相邻不同颜色数直接和分出来的极长颜色段数量有关,更为具体的,设有 \(k\) 个极长同色段,则相邻的相同颜色对数为 \(n-k\) 对。这启发我们转为求颜色段数。

设颜色 \(i\) 出现了 \(cnt_i\) 次。

首先我们忽略标号,在算完 \(p\) 以后将 \(p\) 乘上 \(\prod cnt_i!\) 即可。那么分 \(k\) 段的方案数是自然的:\(\dbinom{cnt_i-1}{k_i-1}\)(这里要特判 \(cnt_i=0\) 的情况)。所以我们有一个 \(egf:f_i(z)=\sum_{k=1}^{cnt_i}\dbinom{cnt_i-1}{k-1}\frac{z^k}{k!}\)。卷起来得到一个 \(F(z)\)。显然这些多项式的次数总和是 \(n\),所以可以利用分治 + NTT 在 \(O(n\log^2 n)\) 的时间内算出 \(F(z)\) 的各项系数(另一个办法是启发式合并:每次找次数最小的两个多项式,卷起来)。但是 \([z^i]F(z)\) 并不是 \(p_{n-i}\)。因为我们的 egf 在进行组合的时候并不能保证同色段不会被组合到一起。实质上设 \(q_{n-i}=[z^i]F(z)\),则 \(q_i\) 的意思是至少 \(i\) 个相邻相同颜色的排列数。那么显然存在一个二项式反演的关系:

\[p_i=\sum_{j=i}^{n-1}(-1)^{j-i}\dbinom{j}{i}q(j) \]

有趣的是这里也存在一个科技:可以一次卷积求出 \(p_{1\sim n}\)。首先,我们把组合数拆开:

\[p_i=\sum_{j=i}^{n-1}(-1)^{j-i}\frac{j!}{i!(j-i)!}q_j \\ \Rightarrow p_i=\frac{1}{i!}\sum_{j=i}^{n-1}\frac{(-1)^{j-i}}{(j-i)!}j!q_j \\ \]

我们令 \(G(i)=\frac{(-1)^{i}}{i!},H(i)=i!q_i\),则有

\[p_i=\frac{1}{i!}\sum_{j=i}^{n-1}G(j-i)H(j) \]

现在我们只来研究后面的 \(\sum\)。对和式做变换得到

\[p_i=\sum_{j=0}^{n-1-i}G(j)H(j+i) \]

这是一个标准的差卷积 形式。通过把 \(H\) 反转:\(H'(i)=H(n-1-i)\),我们将看到:

\[p_i=\sum_{j=0}^{n-1-i}G(j)H(n-1-i-j) \]

此时变成了一个和卷积,指数下标和固定为 \(n-1-i\)。这种处理差卷积的方法也是一个常见的套路。

现在我们已经求出了 \(p\),最后的任务是通过 \(p\) 还原 \(F\)。我们知道:

\[F_i=\sum_{j=0}^{n-1}p_jj^i \]

通过研究 \(F\) 的生成函数 \(G\),我们将看到:

\[G(z)=\sum_{i=0}^{\infty}F_iz^i=\sum_{i=0}^{\infty}(\sum_{j=0}^{n-1}p_jj^i)z^i \\ \Rightarrow \sum_{i=0}^{n-1}p_i(\sum_{j=0}^{\infty}i^jz^j) \\ \Rightarrow \sum_{i=0}^{n-1}\frac{p_i}{1-iz} \]

直接暴力通分,显然是不行的。如果我们类似分治NTT,分治地通分,显然复杂度的瓶颈在于求分母:这就是分治NTT,所以复杂度还是 \(O(n\log^2 n)\) 的。

这样,我们就变成了求一个生成函数的 \(z^1\sim z^m\) 项系数。它形如:

\[G(z)=\frac{s(z)}{t(z)} \]

此时求 \(t(z)\)\(z^{m+1}\) 意义下的逆 \(t^{-1}(z)\),然后直接求 \(s(z)t^{-1}(z)\) 的对应项系数即可。

时间复杂度 \(O(n\log^2 n+m\log^2 m)\)

记录

8. Bowcraft

不是很难,但对我很难。

首先容易考虑到:设 \(dp(i)\) 表示 \(i\rightarrow n\) 的期望步数。然后 \(dp(i)\) 会有一个对所有 \(a,b\) 都不同的转移。

这个转移的形式是取 \(\min\) 的,而且与 \(dp(0),dp(i),dp(i+1)\) 有关,所以这样直接下去是没有任何出路的。

这个题有意思的地方就在于通常无往而不利的倒着设计 dp 状态反而行不通,在出现诸如“清零”这样情况的时候直接正着做有奇效。

\(dp(i)\)\(0\rightarrow i\) 的期望步数,对于一个 \(a,b\),设 \(\alpha = \frac{a}{A},\beta = \frac{b}{B}\),我们将看到:

\[dp(i)=\min\{dp(i)+1,dp(i-1)+1+(1-\alpha)\beta dp(i)+(1-\alpha)(1-\beta)(dp(i)-dp(i-1)) \} \]

然后常规地比较 \(\min\) 不取 \(dp(i)+1\) 的时候发生了什么,我们将看到这说明:

\[f(n)\ge \frac{\alpha+\beta-\alpha\beta}{\alpha}f(n-1) \]

所以当我们按照 \(\frac{\alpha+\beta-\alpha\beta}{\alpha}\) 排序后,不取 \(dp(i-1)+1\) 的物品是一段前缀。

枚举前缀长度,对所有可能取 \(\min\) 即可。时间复杂度 \(O(kAB)\)

我们理一下发现一个难点是想到正着做。因为有个清零,如果你倒着,\(dp(i)\) 肯定会出现 \(dp(0)\),但是这种情况如果是正着做只不过依旧是 \(dp(i)\) 罢了。还有一个点,是正着做的转移并不好推,这里实际上是从刷表的角度去推的,即从 \(i-1\) 去推到 \(i\)。我们注意到有一个 \(f(i)-f(i-1)\) 实际上是利用了期望线性性:\(0\rightarrow i\) 的期望等于 \(0\rightarrow i-1\) 的期望加上 \(i-1\rightarrow i\) 的期望。

记录

9. Xor Tree

考虑如果修改了 \(u\),则所有经过 \(u\) 的路径都将可以合法( \(a_u\) 取一个极大的 \(2^k\)),所以我们可以视作把 \(u\) 删掉,形成两颗独立的树。

\(f_u\)\(u\) 到根的异或和,经典套路是 \(d(u,v)=f_u\oplus f_v\oplus a_{lca}\)

显然从下往上地枚举 \(u\) 作为 \(lca\),若有以它为 \(lca\) 的路径不合法,则删除点 \(u\)。这个贪心成立,我们假设 \(u\) 子树内路径全部合法,在 \(u\) 处第一次出现不合法,则我们要么删除 \(u\),要么删除这条不合法路径上的其它任意一点。你发现删 \(u\) 是最优秀的,因为可以减少继续向上传递的点数最多。

所以我们要 check 是否有跨越 lca 的不合法路径,预处理 \(f\) 以后 dsu on tree 即可,太典了。

记录

10. Slayers Come

显然每个技能贡献一个区间,然后变成了选择若干区间覆盖 \([1,n]\) 的方案数。

这是个经典问题。首先我们按照 \(r\) 排序(\(r\) 相同按照 \(l\) 降序排序)。然后考虑设 \(dp(i)\) 代表 \([1,i]\) 被覆盖且 \(i+1\) 没有被覆盖的方案数。

当我们加入一个 \([l,r]\) 的时候,显然 \(dp(r)\) 会加上 \(\sum_{i=l-1}^{r}dp(i)\)。另外,对于 \(i\le l-2\)\(dp(i)\)都应该乘上 \(2\)(因为选它和不选对覆盖的极长前缀是不受影响的)。用线段树维护即可。复杂度 \(O(m\log n)\)

记录

11. Foul Play

没做出来多少有点菜了。

题目明示一定有解。所以,只要 \(N=2^n\) 且满足至少有 \(\frac{N}{2}\) 个人可以直接被击败,记作 \(S\),不能直接击败的人,必定可以被一个 \(S\) 中的人击败。

只要满足上面的条件,就一定有解。我们考虑构造地证明这件事,也就做完了题目。

\(n=1\) 的情况是平凡的。

考虑 \(n\ge 2\),设有 \(a\) 个人不能被直接击败,则 \(a\lt 2^{n-1}\),考虑把这些人两两匹配,则还会剩下 \(\left\lceil \frac{a}{2} \right\rceil\) 个这样的人,当 \(a=2^{n-1}-1\) 的时候这是不合法的,因为在下一轮 \(a=2^{n-2}\)。但是注意到我们并没有利用这 \(a\) 个人分别能被 \(S\) 中的一个人击败这条性质。同时我们也不能保证在下一轮里,这 \(a\) 个人存活下来的人,每个都能被存活下来的 \(S\) 中的某个人击败。

考虑这样一个贪心的匹配:

不断寻找 \((x,y)\),满足 \(x\in S\)\(y\notin S\),且 \(x\) 可以击败 \(y\),然后让他们匹配。直到寻找不到这样的 \((x,y)\) 为止。

然后我们再让不能被 \(1\) 直接击败的人自相残杀。

最后把剩下的人随意配对(注意优先配对 \(1\))。

这样,不能被击败的人(设为 \(B\)),有些会被直接干掉,而且至少会被干掉一个(这就保证了个数不会大于等于 \(2^{n-2}\));如果 \(B\) 的某个人 \(x\) 不被干掉,它就存活到了下一轮,根据上面的贪心过程,我们发现所有击败这个人的人,已经和其它的人打过并且胜出了,所以一定有一个存活下来的人 \(X\in S\),满足 \(X\) 可以打败 \(x\),这就满足了第二点。

通过这样归纳的构造,就证明了一定有解。时间复杂度 \(O(N\log N)\)

记录

12. Game on Graph

比较基础的前置是 ABC209E,一年前让我很痛苦的题。

这类题首先我们可以对 dag 的情况设计一个显然正确的 dp:设 \(f(u,0)\) 是位于 \(u\),轮到先手移动的结果(如果陷入环就是 \(\infty\)),\(f(u,1)\) 是后手的状态。然后就有

\[f(u,0)=\min_{u\rightarrow v}\{f(v,1)+w_{u\rightarrow v}\} \\ f(u,1)=\max_{u\rightarrow v}\{f(v,0)+w_{u\rightarrow v}\} \]

现在考虑一般图的情况。把我们的目标从另一个角度考虑:不是“计算” \(f\),而是“构造”满足上述约束的 \(f\),同时我们注意到若 \(u\) 无出度,则我们确认了若干初始状态,然后再和上面的约束统一。

事实上这个想法让我想到了解线性齐次递推式的过程:比如解 \(f_n=3f_{n-1}+2f_{n-2}\),我们会先对 \(f_n\) 进行构造使得满足 \(f_n-3f_{n-1}-2f_{n-2}=0\) 成立,然后将初始项 \(f_1,f_2\) 代入,确定整个 \(f\) 的解。其实上面的 dp 也是类似的思想。

从“构造”的角度来观察可以解决很多说不出来的迷惑。

然后考虑调整:我们先把所有状态的值设为 \(\infty\)(对于一般的问题,这个初始值的设置需要一点智慧,但通常都是很特殊的值,例如 \(0,\infty,-\infty\) 等,我们只需要最后检验是否满足约束即可),这样满足我们的约束,但是并没有和初始值达到统一。然后,考虑从确定为 \(0\) 的终止状态反推,去调整不满足约束的状态。

比如如果 \(3\rightarrow 5\) 有边,且 \(5\) 无出度,那么 \(f(3,0)\) 一定不会是 \(\infty\) 了,这就是一个调整。

显然一个点只有被调整了,才会去对其他点产生新的约束。我们考虑把被调整过且未去对其他点进行影响的点按照值升序排序,每次取最小的更新(其实是一个dijkstra的过程)。

考虑 \(f(u,0)\) 只要被更改,就可以压入队列,而对于 \(f(u,1)\),只有它能到达的每个 \(v\)\(f(v,0)\) 的值都被修改了,它才会被修改,否则必定有一个 \(f(v,0)=\infty\),那么 \(f(u,1)\) 也就是 \(\infty\)

通过这样一个“构造”过程的推导,就可以解释清一个类似反向拓扑+dijkstra做法的原理。

事实上这是一类比较有趣的题型,其思想看上去也很能有进一步应用,虽然我还没得到什么有趣的 idea,也许未来会被出成别的题也说不定。

记录

13. Multiset of Strings

这个题的约束看起来很多很恐怖,考虑建 trie。然后我们发现这是一颗 \(n+1\) 层满二叉树且我们会选择若干叶子(一个叶子可能被选多次),一个叶子被选了 \(k\) 次,就会把到根的路径上每个点加上 \(k\),设一个点 \(u\) 的值是 \(c_u\),则它的子树内选择的点的次数和 \(\le c_u\)。这就把问题转成了一个可做的形式。

但是子树点的次数和 \(\le c_u\)\(\max=f\) 的必要条件而不是充分条件,因为你可能选出来 \(\gt f\) 个点。

考虑设 \(f(u,i)\)\(u\) 子树最多只能选 \(i\) 个点的方案数,则我们有转移:

\[f(u,i)=\sum_{x+y=i}f(v1,x)f(v2,y) \]

但考虑还有这样一种情况:左子树最多能选 \(5\) 个,右子树最多能选 \(3\) 个,而 \(c_u=7\),则它会贡献到 \(f_{u,7}\) 上,所以最终的 dp 方程是:

\[f'(u,i)=(k-i+1)\times f(u,i)+\sum_{j\gt i}f(u,j) \]

然后因为是满二叉树,本质不同的 \(dp\) 状态只有 \(n\) 个,所以做 \(n\) 次卷积即可。

\(N=2^n\),时间复杂度为 \(O(n^2\times N)=O(N\log^2 N)\)

记录

14. Doubly-sorted Grid

来自十年前的神题。

注意到如果填完了前 \(i\) 个字符,则右边界一定随着行的增加而递减。事实上把整个网格看成一个 \((0,0)\sim (n,m)\) 的坐标系,则左下角是 \((0,0)\),右上角是 \((n,m)\),右边界等价于从 \((0,0)\) 出发,每次向上或向右走一步,走到 \((n,m)\) 的一条路径。

所以路径只有 \(\dbinom{n+m}{n}<=2\times 10^5\) 种,我们记这个数目为 \(\omega\)

对所有边界进行重新编号后我们考虑设 \(f(x,i)\) 代表前 \(x\) 种字符填完,形成的轮廓线编号为 \(i\) 的方案数,通过适当的对边界线排序,我们会发现有类似的一个形式:\(f(x,i)=\sum_{j\lt i}f(x-1,j)\),其中 \(j\) 完全要被 \(i\) 包含进去,同时你还得判断 \(i-j\) 这一段是否都能填字符 \(x\)

但是这样我们发现很难做到低于 \(\omega^2\) 的复杂度,仍然不能通过。

考虑如果第 \(x\) 个字符出现了(如果没出现答案就是 \(f(x-1,i)\)),那么必定会首先在轮廓线的某个拐点出出现,所以我们可以枚举 \(O(m)\) 个拐点,在 \(2^m\) 的时间内枚举哪些拐点出现了字符 \(x\),然后去进行容斥(比如说有两个拐点 \(A,B\),那么就是 \(A\) 出现 + \(B\) 出现 - \(A,B\) 都出现)。这样你就可以单次 \(O(2^m)\) 的转移。

这里实现上要作注意,如果是第一层枚举 \(x\),第二层枚举 \(i\),然后枚举所有可能的 \(2^m\) 个状态,然后你还要 \(O(n+m)\) 处理出新的状态,最后可能还要带一个 map 查询的 \(log\),那么复杂度就变成了 \(O(26\times \omega\times 2^m\times (n+m)\times \log \omega)\),这显然是恐怖的。实践证明这个做法至多也只能通过 \(n,m\le 9\) 的做法(而且是在本题 15s 的恐怖时限下)。

但是考虑对所有相同的 \(i\),其实 \(2^m\) 个状态里有很多重复的东西。具体来说,我们可以先更改转移顺序:先枚举 \(i\),再枚举 \(x\),然后对于每次的 \(i\),把 \(2^m\) 个状态具体是什么预处理出来,并且把它们的限制处理出来(要么 \(x\) 取任何值都有效,要么 \(x\) 取某一个值有效,要么无效),同时把它们的编号先用 map 问出来然后存起来,这样不考虑内层转移,复杂度是 \(O(\omega\times 2^m\times (n+m)\times \log \omega)\),相当于你砍掉了一个 \(26\) 的常数;然后内层的复杂度是 \(O(\omega \times 26\times 2^m)\),相当于砍掉了 \((n+m)\log \omega\) 的系数。这样就可以通过本题。

似乎本题还可以进一步加速:把容斥的过程压进 dp 里,再开一维。但我并不是很会这个做法,如果有人会的话欢迎教教。

记录

15. Year of More Code Jam

又是十年前的神题,不过比上面的简单很多。

首先根据期望线性性,我们转为对单个位置求期望。

\(x_{i,j}\)\(i\) 号比赛是否会有一场在第 \(j\) 天举办,则我们将看到:

\[E(a_i)=\sum_{j=1}^{m}\sum_{k=1}^{m}E(x_{j,i})E(x_{k,i}) \]

(这个技巧其实对任意次方都是成立的)

考虑一轮锦标赛,只会有最多一场在同一天举办。所以可以设 \(y_{i,j,k}\) 表示 \(i\) 号比赛的第 \(j\) 场是否会在第 \(k\) 天举办,则有:

\[E(x_{i,j})=\sum_{k=1}^{cnt_i}E(x_{i,k,j}) \]

把这个展开式放到最上面的式子,我们发现我们会对所有 \((a,b,c,d)\) 四元组去计算,四元组的意义是 \(a\) 锦标赛的第 \(b\) 场,和 \(c\) 锦标赛的第 \(d\) 场同时在第 \(j\) 天举办的期望。我们将发现剩下 \(m-2\) 个锦标赛的取值是无所谓的。又因为这里权值是 \(1\),所以期望就是概率。那么分母就是 \(n^2\)(如果 \(a=c\) 那么就是 \(n\),这种情形需要特殊考虑),而分子其实要么是 \(1\),要么是 \(0\)

我们发现 \(n=10^9\),所以不可能对每个位置算一下再加起来,但你注意到所有位置的期望的分母都是 \(n^2\),所以我们只关注所有位置的分子的和。而你枚举 \((a,b,c,d)\) 后就可以简单计算出这个四元组对多少个位置的贡献是 \(1\)(对于 \(a=c\),我们把分子分母同时乘上 \(n\),那么也容易计算它对多少个位置的贡献是 \(n\))。这样就在 \(O((m\omega)^2)\) 的时间内解决了问题,其中 \(\omega=\max\{len_i\}\)

记录

16. 钥匙

对我而言难度适当质量还不错的好题。

首先每种颜色的过程是独立的,这启示我们分开来对每种颜色单独考虑:这就引出建虚树的想法。

然后注意到颜色相同的情况下,钥匙之间没有本质区别,宝箱之间没有本质区别,分别视作 \(+1\)\(-1\),我们发现实质上类似一个括号匹配的过程。

注意到此时只有 \(5\) 个钥匙,暴力枚举一个钥匙 \(x\),再枚举宝箱 \(y\),他们两能匹配当且仅当它们路径中间的同颜色点是匹配的。

所以你可以从每个钥匙为根然后对虚树 dfs,然后就可以找到所有的 \(y\),容易发现总共的 \((x,y)\) 点对不超过 \(O(n)\) 级别。

然后变成了这样的一个问题:给出若干条路径 \(s\rightarrow t\)(有向),你需要把所有路径上包含 \(s\rightarrow t\) 的路径的权值 \(+1\),然后询问若干条路径的权值。

考虑一条路径能被起点和终点两个点描述,假设 \(s\)\(t\) 不是祖先关系,我们会看到:只有起点位于 \(s\) 子树,终点位于 \(t\) 子树的路径,才会被 \(+1\)。放到二维的 dfs 序平面上,这对应了一个矩形。而对于 \(s\)\(t\) 是祖先关系的情况,有类似的讨论。所以问题变成了若干个矩形加后若干个单点查询,扫描线即可处理。

值得注意的是这样的题尽量使用树剖求 lca,我使用倍增几乎是贴着时限过去的。

时间复杂度 \(O((n+m)\log n)\)

记录

17. Treasure

还没有上面那个有趣的 trash 题。

不难想到建 kruskal 重构树然后变成子树查询。

注意到一种颜色只会出现 \(10\) 次,每种颜色是独立的,所以考虑修改一次,就对这个颜色的点建出虚树,然后 dfs 虚树,在点 \(u\) 到他父亲之前的这条链答案是固定的,所以变成链加单点求和,通过树上差分改为单点加子树求和即可。复杂度 \(O(q\log n)\),常数为 \(10\)

赛后 hdoj 的机子实在太慢了,所以要很极限地卡常。

记录

18. 树的计数

很有趣的思维题。

考虑到我们求的就是树高的期望,这提示我们很有可能我们并不是先对高度为 \(i\) 的合法的树去计数。

注意到树高就是 bfs 序分的层数 \(+1\),所以我们可以考虑把这个问题变成 bfs 序分的层数的期望,而根据期望线性性,它等于每个位置 \(i-(i+1)\) 之间分层的期望。

注意 \(k=0\) 的话是 \(\infty\),而题目没有特殊说明,所以暗示了题目的输入保证了至少存在一个合法的树。

只给出 \(dfs\) 序当然是没法确定唯一树的,只给出 \(bfs\) 序当然也不行,但是如果既给出了 \(dfs\) 序,又利用 \(bfs\) 序确定了每个点的 \(depth\),那么结论是只可能确定出一颗树(当然也可能矛盾,导致没有符合条件的树)。

考虑从根开始,然后下一个节点,我们知道了 \(dfs\) 序中当前节点和下一个节点的 \(depth\),那么就知道“下一个节点”在这颗树中应该是哪个点的儿子(所以有 \(depth_{d_{i+1}}\in [2,depth_{d_{i}}+1]\),另外我们发现按照这个顺序,另外,遍历是有顺序的,比如如果在 bfs 序中 \(5,3\) 同层且 \(5\) 先出现,则在 \(dfs\) 序中 \(5\) 也应该先出现。我们发现,第一个条件的合法让我们能确定树结构,第二个条件的合法让我们遍历节点的顺序不会有矛盾。

那么就分析的差不多了。我们为了方便起见,首先把 \(bfs\) 序转成 \(1\sim n\) 的形式,然后,如果 \(i\) 的位置,在 \(dfs\) 序中,晚于 \(i+1\) 出现,则 \(i-(i+1)\) 必须分段。在必须分段的点确定过后,设 \(dfs\) 序中第 \(i\) 个位置是 \(d_i\),如果 \(d_i<d_{i+1}\),那么 \([d_i d_{i+1})\) 中最多只能有一个分段点。这样,有一些点就一定不能分段。

一定分段的点,对期望的贡献一定是 \(1\);不能分段的点,对期望的贡献一定是 \(0\)。那么,剩下的未确定的呢?我们会发现一个问题:我们怎么处理形如:一个区间只能有至多一个点选 \(1\),其它点选 \(0\) 这样的约束呢。

这里要有一个整体的观念,就是说 \(dfs\) 序一定是一个 \(1\sim n\) 的排列。如果 \(d_i+1=d_{i+1}\),那么你只对 \(d_i\) 一个位置做约束,那么它选不选随意;如果 \(d_i+1\lt d_{i+1}\),那么所有大于 \(d_{i}\) 且小于 \(d_{i+1}\) 的数都会排布在 \(i-(i+1)\) 的两侧。我们会意识到,这就意味着 \([d_i, d_{i+1})\) 中一定存在至少一个点分段了,那么这个区间的其它点已经被确定只能不分段,就不存在问题了。

所以我们得出结论,此时没被约束的点确实是独立的,贡献为 \(0.5\)

记录

19. The Lost House

比上面那个思维简单很多,但是模拟的时候因为排序 fst 了......

\(f(u)\) 是当前位于 \(u\),答案位于 \(u\) 的某个子树,找到的期望步数。那么当答案不在 \(u\) 子树的时候怎么处理?我们发现此时一定会在若干次搜索后走回到 \(u\) 再走回去,所以设 \(g(u)\) 是答案不在 \(u\) 子树,走回去的步数(这里不是期望,因为你已经确定了答案不在 \(u\) 子树,但是主人公还不清楚这个事实)。

\(g\) 的转移是容易的:如果当前点有一个虫子,那么就是 \(g(u)=2\),否则 \(g(u)=2+\sum_{v}g(v)\)

那么 \(f\) 呢?我们是对所有 \(u\) 的儿子的排列 \(v_1,v_2,...,v_k\),最小化这个式子:

\[\sum_{i=1}^{k}\frac{cnt_{v_i}}{cnt_u}\times (\sum_{j\lt i}g(v_j)+f(v_i)+1) \]

\(cnt_u\)\(u\) 子树内的儿子个数。

我们发现 \(f\) 相关的项是确定的,问题在于最小化 \(\sum prob\times presumg\)

到这里就是简单的 exchange-argument 问题了,通过研究相邻两项的关系,我们会发现把儿子按照 \(\frac{g}{cnt}\) 来排序是最优秀的。

时间复杂度 \(O(n\log n)\)

记录

20. Garbage Collector

这个题模拟没搞出来有点降智了。

容易往一个方向去想:一次行动会把一个区间的垃圾带回来,但是其实是错误的。如果上来就直接利用这个结论然后去斜率优化就彻底误入歧途了。

但是一个策略是确定的:假设我们一次行动,把带回来的垃圾按照坐标排序,记为 \(x_1,x_2,...,x_m\)。那么我们的移动策略是什么?一定是先移动到 \(x_m\),然后往回走,路途中再带上要收集的垃圾。

我们来推一下答案:不妨把 \(x\) 倒转,那么答案就是 \(x_{1}+\sum_{i=1}^{m}(i+1)^2(x_i-x_{i+1})\),我们定义 \(x_{m+1}=0\)

化简以后得到 \(5x_1+\sum_{i=2}^{m}(2i+3)x_i\)

我们把系数列出来会发现就是 \(5,5,7,9,11,13,15,...,\)

如果放下垃圾没有代价,我们会发现一次搬一个垃圾是最优秀的。

如果放下垃圾有代价 \(X\) 呢?自然想到枚举这个次数,然后我们就只用让上面的贡献最小。距离原点越远,它对应的系数就会越小。我们假设用了 \(k\) 次,那么把系数列出来以后就很容易想到最优秀的构造方式:最远的 \(k\) 个给第一个 \(5\),次远的 \(k\) 个给第二个 \(5\),接下来的 \(k\) 个给 \(7\),然后给 \(9\),......,依次类推。不难发现预处理 \(x\) 的前缀和以后可以做到 \(O(n\ln n)\)

记录

21. Ants on a Circle

感觉这种题对我来说能不能做出来完全随缘了......

有一个想法是我们把掉头这个事情忽略掉,因为宏观上来看就是直接穿过去了。这样我们确实可以找到所有蚂蚁结束的位置,但是我们并不能建立起一一对应。

自然地会给蚂蚁分配一个编号,当它们碰撞的时候,蚂蚁继续往前走,交换编号。

我们容易知道每只蚂蚁最后的位置,所以我们只需要求出它们各自的编号即可。

如果我们重新把蚂蚁按照输入顺序编号为 \(0\sim n-1\) 的话,我们考虑所有碰撞中,所有最早发生的碰撞:它一定是编号相邻的两个蚂蚁。

然后会发生什么?顺时针的那只,编号将 \(+1\)(模 \(n\) 意义下),逆时针的那只,编号将 \(-1\)

然后把最早的碰撞考虑过后,我们来看目前的局面。此时再去研究次早发生的所有碰撞:我们发现通过归纳可以得出,当两只蚂蚁碰撞的时候,顺时针的那一只编号 \(+1\),逆时针的那只编号 \(-1\)

讲个笑话,我模拟的时候手玩了半天都没发现这个编号更改的规律。

那么有了这个规律以后我们就只关注蚂蚁碰撞的次数了。不妨假设我们当前枚举的是一只顺时针的蚂蚁,那么考虑所有逆时针的蚂蚁。每 \(L\) 秒它显然会和每只逆时针的蚂蚁撞 \(2\) 次。所以我们令 \(t=T\bmod L\),然后找到多少只蚂蚁会和我们枚举的碰撞一次,多少只会碰撞两次即可,可以通过二分来找到。

逆时针也是同理的。然后我们就知道了每只蚂蚁的终止位置和终止时刻的编号,然后这个问题就做完了。

但是我的实现确实很丑,这是值得思考的。

记录

22. Travel plan

仙人掌基础练习题。

首先我们知道路径的权值 \(\gcd\)\(k\) 可以通过莫比乌斯反演来变成:路径权值为 \(k\) 的倍数的路径条数。

但是一般图的简单路径条数显然是个不可做问题...... 光是考虑两点之间的路径条数就很困难了。

所以这个图一定存在某些性质。题目里告诉我们:不存在边权和为偶数的简单环。

那么首先肯定不是树了。直觉比较好的话,很快会猜出来是仙人掌。感谢 zimpha 在这里给了一个简明易懂的证明:

考虑一个边权和为奇数的简单环。如果它有一条弦,那么分成的左右两个弧必定奇偶性不相同,这两个弧一定能取出一个,和这条弦组成一个小的简单环,满足边权和为偶数。

因此任何一个简单环内部不能存在弦。这就自然地引导出图是一个仙人掌。

然后问题变成了仙人掌上的简单路径计数。不难发现,建圆方树过后,两点 \((u,v)\)(圆点)之间简单路径个数是 \(2^{cnt}\),其中 \(cnt\)\(u-v\) 路径上的方点个数。

因此对仙人掌做简单树上 dp 即可。

时间复杂度不是很会算........ 看上去是调和级数但你考虑一个权值的边不会只出现一条,所以感觉是 \(m\times \omega\) 的,其中 \(\omega\)\(\max_{i=1}^{L}d(i)\)\(d(i)\) 是因子个数。肯定是比 \(m\ln m\) 慢不少的。

但我本地不加任何改动也就 2s 啊,hdu 的机子真的是慢出一定境界了。

记录

posted on 2022-07-16 11:40  Cry_For_theMoon  阅读(195)  评论(0)    收藏  举报