计数做题记录

9ed8dc3cf19471e3efdb8b7f0c5e1d4f111

「ARC101E」Ribbons on Tree

直接做有点困难,考虑正难则反,对没有颜色的边操作。

那么考虑钦定一些边没有颜色,相当于把它们断开,要求形成的每个连通块内的所有边都有颜色。块内方案数是简单的。那么考虑树形 DP,记 \(f_{i,j}\) 表示以 \(i\) 为根的子树内,\(i\) 所在连通块大小为 \(j\),除了 \(i\) 所在连通块的其他连通块的方案数。转移是简单的。复杂度就是树上背包,\(O(n^2)\)

https://atcoder.jp/contests/arc101/submissions/68619248

「CF1874F」Jellyfish and OEIS

这有完整题解

同样正难则反,考虑对是排列的区间容斥。本题有一个很好的性质,就是交错的区间交错部分容斥系数会抵消,那么我们只需要容斥包含关系和不交关系的区间即可,大致是个树型结构,然后区间 DP 一下即可。容斥系数就是钦定为排列的区间数量。

https://codeforces.com/contest/1874/submission/334395243

「ARC168C」Swap Characters

这有完整题解

一个有点神秘的计数,对结果序列刻画,考虑把三种字符视作三个节点,然后建一个完全图,\(a\rightarrow b\) 的边权就是最后字符串上本来是 \(a\) 的字符变成 \(b\) 的数量。考虑枚举边权,由字符数量不变可得各点自己的出度等于入度,那么只需要 \(k^4\) 即可枚举边权。

考虑贪心判断一种状态是否可行,那么就要最小化操作次数。那么有效的交换只有两种,要么两个互换,要么三个轮换。不难发现,我们可以尽可能地先两个互换,那么操作一次一对反边的边权各减一,直到无法操作,剩下的必然是一个单向环且环上各边等权,这么贪心必然不劣。

至于一种状态对应的字符串数量,多重组合数计数每个字符分别把哪些位置变成了另外两个字符即可。

https://atcoder.jp/contests/arc168/submissions/68628909

「ARC174E」Existence Counting

考虑容斥,下文中的“所有序列”满足题中的长度、值域与互不相同限制:

\[所有序列-字典序超过要求的序列-不包含给定数的序列+字典序超过要求且不包含给定数的序列 \]

第一种和第三种是易求的,考虑第二种,枚举第一个超过给定序列的位置即可,用树状数组维护之前出现过的数可以做到 \(O(\log n)\)

考虑第四种,类似第二种的方法求,额外开一棵树状数组存每个数的答案,那么枚举到的位置之前的数必然出现过,因此给定序列中出现的数在枚举到对应位置时就要查询,剩下的最后再查。每次更新答案分讨一下在给定序列上方还是下方即可。没有很困难。

https://atcoder.jp/contests/arc174/submissions/68629885

「ARC186A」Underclued

这有完整题解

矩阵上行列限制,很典的思路就是建二分图,一侧为行,一侧为列。

这题建图有点巧妙吧,\(1\) 连正边,\(0\) 连反边,那么未被固定的点必然在这个图上的环中,因为反转环各点入度不变。

那么 \(f_{i,j}\) 表示左侧 \(i\) 个点右侧 \(j\) 个点的方案,转移枚举新的环左右侧点数 \(l,r\) 即可,这个新的连通块内新增的 \(lr\) 条边必然全在某个环中。然后就暴力 DP 吧。

https://atcoder.jp/contests/arc186/submissions/68632760

「ARC157E」XXYX Binary Tree

这有完整题解

本题关键在于 y 点,不难发现要选一个独立集,并且通过组合计数可以得到要求的叶子节点 y 数量与非叶子节点 y 个数。考虑树上 DP,直接三维可行性 DP 有点炸,优化一下,考虑对一种叶子 y 节点数找到最多的非叶子 y 节点数即可,这样优化之后就是 \(O(n^4)\) 的。

https://atcoder.jp/contests/arc157/submissions/68635569

「ARC165E」Random Isolation

这有完整题解

很巧妙的转化吧,但貌似有点典。

考虑可以对一个连通块统计其出现的概率,一个连通块出现当且仅当连通块内各点均未被删除,且与连通块相连的非块内点均已被删除,这个 DP 状态设计是好做的,我们只需要知道当前连通块点数与与之相连的点数,接下来就是求概率,这个就有点巧妙了:

原问题等价于一个 \([1,n]\) 的随机排列 \(P\),顺次遍历这个排列,若当前点所在连通块大小超过 \(k\) 就操作否则跳过的期望操作次数。这个之所以等价是因为每次操作后剩下的有效的点会等概率出现。因此上面的问题相当于一个任意排列上要求 \(a\) 个点完全在 \(b\) 个点前面的方案数,显然为 \(\frac{a!b!}{(a+b)!}\)

https://atcoder.jp/contests/arc165/submissions/68638018

「CF1295F」Good Contest

离散化一下,分 \(O(n)\) 段,然后 \(f_{i,j}\) 表示考虑前 \(i\) 道题,最后一道题的值在第 \(j\) 块的方案,不同块的转移是简单的,同块转移就有点麻烦,考虑枚举最后有多少道题属于同块,然后枚举这些题里有几个不同的值也就是分了几段,再在这一块的值域里选出段数个数即可,这个组合计数是好做的。

https://codeforces.com/contest/1295/submission/334729121

「CF1093F」Vasya and Array

\(f_{i,j}\) 表示前 \(i\) 个数,第 \(i\) 个数填了 \(j\) 的方案数,考虑容斥掉不合法情况,也就是最后一段超过 \(len\) 的情况,那么就要求最后 \(len\) 个数全都可以填成 \(j\),这个滑动窗口桶计数即可,但要加上长度为 \(len+1\) 的情况,因为这种情况在 \(f_{i-1,j}\) 已经消去了,不需要多减。

https://codeforces.com/contest/1093/submission/334732186

「ABC180F」Unbranched

先忽略最大值为 \(L\) 的影响,跑两边,用 \(\le L\) 的答案 减去 \(<L\) 的答案即可。剩下的就简单了,\(f_{i,j}\) 表示前 \(i\) 个点有 \(j\) 条边,然后枚举最后一个连通块的大小转移即可,组合数学部分并不难。

https://atcoder.jp/contests/abc180/submissions/68683642

「AT_tokiomarine2020_e」O(rand)

这有完整题解

判个无解,重点就在于要选一些合法数使得 \(S\oplus T=1\) 的位置有的数为 \(0\) 有的数为 \(1\)。反向计数,统计选的全为 \(0\) 或全为 \(1\) 的方案数,也就是按位与这些位之后选的数全都相等,然后钦定一些位满足不合法条件容斥一下即可。

https://atcoder.jp/contests/tokiomarine2020/submissions/68684684

「AT_mujin_pc_2018_f」チーム分け

这有完整题解

要求一组内最小的 \(a\) 不小于组大小,有点复杂,考虑先降序排序,那么只用考虑最后一个数,就方便转移了,\(f_{i,j}\) 表示前 \(i\) 个人 \(j\) 个已经被分组的方案数,然后枚举最后一组大小即可,\(O(n^3)\) 可过。正解看题解链接吧。

https://atcoder.jp/contests/mujin-pc-2018/submissions/68685163

posted @ 2025-08-22 11:36  LastKismet  阅读(14)  评论(0)    收藏  举报