计数题目合集
CF1342F
很巧妙的一个计数题。
原题目等价于构建一个递增序列 \(p\),赋予每个数字一个属性 \(b\),满足 \(b_{p_i}=p_i\),其余任选。且 \(\forall j,\sum\limits_{i=1}^n [b_i=p_j]a_i<\sum\limits_{i=1}^n [b_i=p_{j+1}]a_i\)。最大化递增序列 \(p\) 的长度。
先考虑一个朴素 dp,设 \(f(S,i,j,k)\) 表示已经把 \(S\) 集合中的数填上了 \(b\),考虑当前填到了 \(p_i\),\(p_i\) 填 \(j\),\(\sum\limits_{p=1}^n [b_p=j]a_p=k\) 所能划分出的最多集合数,复杂度高到了天上去。
考虑优化这个 dp,上来发现 \(i\) 没有用,状态变为 \(f(S,i,j)\) ,含义为把 \(S\) 集合中的数填上了 \(b\),考虑当前填到的 \(p\) 是 \(i\),\(\sum\limits_{p=1}^n [b_p=i]a_p=j\) 所能划分出的最多集合数。注意到现在的瓶颈在于我们把值域塞进了状态。我们考虑进一步从这个方面入手。
一个常见的 trick 是把值域和状态互换,考虑这样做的可行性。显然如果 \(f(S,i,j)<f(S,i,k)\land j>k\),则 \(f(S,i,j)\) 无用。也就是说,我们可以把状态 \(f(S,i,j)\) 转化为 \(g(S,i,f(S,i,j))\) 而转去做 \(j\) 的最小值。重新明确一下状态,\(f(S,i,j)\) 表示把 \(S\) 集合中的数填上了 \(b\),考虑当前填到的 \(p\) 是 \(i\),当前划分了 \(j\) 个集合,\(\sum\limits_{p=1}^n [b_p=i]a_p\) 的最小值。
考虑转移。每次去划分一个集合,设当前状态为 \(f(S,i,j)\),枚举 \(S\) 的补集的子集 \(T\),满足 \(\exists p\in T,p\ge i\),且 \(\sum\limits_{i\in T} a_i\ge f(S,i,j)\)。令 \(p_0\) 为满足条件一的 \(p\) 的最小值,则有转移 \(f(S,i,j)\rightarrow f(S\cup T,p_0,j+1)\),\(f(S\cup T,p_0,j+1)\) 对 \(\sum\limits_{i\in T}a_i\) 取最小值。时间复杂度 \(O(3^n n^2)\)。
CF1392H
期望好题!
下文中我们称鬼牌为 joker。
首先注意到每轮抽到 joker 后的局面都是一样的,因此不妨先考虑每两张 joker 之间的答案是期望是多少,那么大概有如下式子:
注意到后面那一堆显然有递推关系,令 \(g_i=\prod\limits_{j=1}^{i}\frac{n-j+1}{n+m-j+1}\),那么我们有 \(g_{i+1}=\frac{n-i}{n+m-i}g_i\),此时上式写成了下面的形式:
可以线性计算。
接下来考虑期望抽的轮数。 注意到牌和牌之间是无标号等价的,那么设 \(f_i\) 表示当前剩下了 \(i\) 张牌没有抽到的期望轮数。注意到一个很重要的事情,一张抽到过的牌是没有用的,因此我们不妨直接看做不放回抽卡!
那么此时可以写出转移式,\(f_i=\frac{m}{m+i} (f_i+1)+\frac{i}{m+i}f_{i-1}\)。移项变形后可得 \(f_i=f_{i-1}+\frac{m}{i}\)。更近一步得到 \(f_n=f_1+\sum\limits_{i=2}^n\frac{m}{i}\),\(f_1=\frac{m+i}{i}\)。
所以答案即为 \(f_nE\)。
看了一眼题解区发现对于 \(E\) 有更简洁的形式,但是要换一种思考方式或者大力变换。在这里只介绍前者。考虑对于每一轮,他的抽牌是把所有牌抽出来,然后算出前面没有 joker 的牌的数量。那么每张牌对答案的贡献为 \(\frac{1}{m+1}\)。根据期望的线性性,答案为 \(\frac{n}{m+1}+1\)。感觉也很厉害了。
CF1616H
超级计数好题,主打的就是一个敢设状态。
首先看到两两异或建出 01-trie 套路变成按位考虑,下文设 \(l(i)\) 表示 \(i\) 的左子树,\(r(i)\) 表示 \(i\) 的右子树。
尝试一个 dp,设 \(f_i\) 表示以 \(i\) 为根的子树的答案,那么对于一个位置 \(i\),若 \(x\) 的第 \(i\) 位为 \(0\),我们有转移 \(f_i=f_{l(i)}+f_{r(i)}\)。但是 \(x\) 为 \(1\) 就似了,因为这不是个子问题。
怎么办?考虑能不能继续往状态里扔垃圾。我们再加一个点,\(f_{i,j}\) 表示考虑在 \(i,j\) 的子树中选若干个数的答案,那么还是首先考虑边界,如果当前到达叶节点,有 \(f_{i,j}=2^{siz_i+[i\neq j]siz_j}\),其中 \(siz_i\) 表示 \(i\) 的子树中点的数量。
现在考虑转移,对于当前的位置 \(dep\),我们考虑如下转移:
-
\(x\) 的第 \(dep\) 为 \(0\)。
-
\(i=j\)。
这个时候只能选一侧子树,然后合并答案,有 \(f_{i,j}=f_{l(i),l(i)}+f_{r(i),r(i)}-1\)。
-
\(i\neq j\)。
此时对于每颗子树的子树内任选,对于两颗子树之间,一定只能是 \(l(i)\) 配对 \(r(i)\) 或 \(l(j)\) 配对 \(r(j)\),转移即 \(f_{i,j}=(2^{siz(l(i))}-1)(2^{siz(r(i))}-1)+(2^{siz(l(j))}-1)(2^{siz(r(j))}-1)+f_{l(i),l(j)}+f_{r(i),r(j)}-1\)。
-
-
\(x\) 的第 \(dep\) 为 \(1\)。
-
\(i=j\)。
此时子树内任选,有 \(f_{i,j}=f_{l(i),r(i)}\)。
-
\(i\neq j\)。
此时可以随便选,有 \(f_{i,j}=f_{l(i),r(j)}f_{r(i),l(j)}\)。
-
注意要考虑一些空集的边界情况。
CF1503E
一道比较平凡的计数,感觉比上面的简单啊为啥 3100。
看到这种奇怪的计数一般考虑转化充要条件。一个首先的观察是,每一行黄色的连通块必须接 \(1\) 或 \(n\),每一列蓝色的连通块必须接 \(1\) 或 \(m\),否则直接不合法。进一步的观察,发现黄色和蓝色都要是单峰的,否则也直接不合法。再进一步,发现两个峰必须紧邻。
不妨假设现在黄色围成了两个连通块,然后现在我们去枚举两个峰的位置,有一个直观的理解是,从四个角走到峰,把路径和 \(x=1\) 的直线围成的封闭多边形染黄,然后转成对路径计数,这个东西是平凡的网格图路径数计数,式子大概是下面的形式:
蓝色同理。现在我们得到了一个 \(O(n^3)\) 的做法。但是注意到后面的若干项要么只与 \(i,k\) 有关,要么只与 \(j,k\) 有关,那么我们套路交换枚举顺序然后前缀和一下即可做到 \(O(n^2)\)。
注意两个都有两个峰的时候可能会算重,要容斥一下,具体来说是做第二遍的时候强制两个峰不交于一点。
CF1608F
首先考虑 dp 的状态应该有什么,那么显而易见的是要把位置 \(i\) 和当前 \(mex\) 扔进去,然后转移需要知道大于 \(mex\) 的数有啥,但是直接这样做是指数级的。
怎么做?我们考虑把贡献放到 \(mex\) 更改的时候去算。那么我们现在有状态 \(f(i,j,k)\) 表示当前考虑到了第 \(i\) 位,当前的 \(mex\) 为 \(j\),前面一共有 \(k\) 个大于 \(mex\) 的数的方案数。转移时枚举第 \(i+1\) 个填什么,分三类讨论:
- \(a_{i+1}<j\),\(f(i+1,j,k)\leftarrow f(i,j,k)\times j\)。
- \(a_{i+1}>j\),\(f(i+1,j,k+1)\leftarrow f(i,j,k)\)。
- \(a_{i+1}=j\),枚举 \(j'\) 与 \(k'\),\(f(i+1,j',k')\leftarrow f(i,j,k)\times coef\),其中 \(coef\) 是一个经典的组合问题,把 \(k-k'\) 个球放进 \(j-j'\) 个空盒子,每个盒子至少有一个球的方案数。注意这里还需要一个组合数 \(\binom{j}{j'}\) 表示从 \(j\) 个位置中选出 \(j-j'\) 个。
这样做的话复杂度 \(O(n^3k^2)\),难以优化。
怎么办?考虑改变状态,重设 \(f(i,j,k)\) 表示当前考虑到了第 \(i\) 位,当前的 \(mex\) 为 \(j\),前面一共有 \(k\) 种大于 \(mex\) 的数的方案数。此时继续按照上面分类讨论。
- \(a_{i+1}<j\),\(f(i+1,j,k)\leftarrow f(i,j,k)\times j\)。
- \(a_{i+1}>j\),此时考虑 \(a_{i+1}\) 是否出现过。
- 出现过,\(f(i+1,j,k)\leftarrow f(i,j,k)\times k\)。
- 没出现过,\(f(i+1,j,k+1)\leftarrow f(i,j,k)\)。
- \(a_{i+1}=j\),枚举 \(k'\),那么有 \(k-k'\) 个数对 \(j\) 产生影响。枚举新的 \(mex\),有转移 \(f(i,j+k-k'+1,k')\leftarrow f(i,j,k)\times\frac{k!}{k'!}\)。
注意到上面的转移是一个类似于斜对角线转移的东西,那么我们可以去考虑一种前缀和优化,将后两维的加和作为第二维,我们惊奇的发现此时后面的可以做前缀和优化,最后转移过去时除掉系数 \(k'!\) 即可。
时间复杂度 \(O(n^2k)\)。
CF1621G
好厉害的题目!
统计所有的上升子序列不好做,那么套路的转化成对每个位置考虑其对答案的贡献次数。接下来去找充要条件。通过一些简单的观察,我们发现对于每个位置 \(x\),其是否有贡献仅取决于其所处的上升子序列的右端点和满足 \(a_y>a_x\) 的最大的 \(y\) 的位置。那么现在问题转化成了对于右端点在区间 \([1,y)\) 中,包含 \(x\) 的上升子序列个数。至此我们可以有一个多项式做法,具体来说是枚举一个位置 \(x\),然后直接去 dp 经过 \(x\) 的上升子序列个数。这个东西有一个常规的树状数组优化做法。至此我们已经能够做到 \(O(n^2\log n)\)。
然后我被卡在这里了/cf。
下面是一步我没看出来的容斥。我们把经过 \(p\) 且右端点在 \([p,y)\) 中容斥为右端点在 \([y,n]\) 中的。更近一步考虑,我们发现右端点只会在 \(y\) 处,这是因为如果存在一个右端点 \(z>y\),则一定有 \(a_z>a_y\),与假设 \(y\) 是最大的不符。再观察一下,我们发现对于 \([1,x)\) 的处理我们是可以直接做的,最后把系数乘进去即可。
现在问题转化成了经过两个定点的上升子序列个数。但太棒了,这个我不会做。
再次回顾性质,我们发现 \(y\) 是 \(x\) 能到达的最远点!那么我们只需要倒序维护一下每个数字的最远点在哪,然后把值塞进一个另一个树状数组。每次求到一个值的时候,把最大的 \(z\) 满足 \(a_z>a_x\) 的 dp 值拉出来减去即可。
时间复杂度 \(O(n\log n)\),太厉害。
CF1810G
小清新计数题,有很大的启发意义,我上来就被干烂了/cf。
首先考虑一个 naive 的 dp,设 \(f_{i,j,k}\) 表示到达 \(i\) 位置,最大前缀和为 \(j\),当前前缀和为 \(k\) 的期望答案,这样就是一个 \(O(n^3)\) 的做法,但我们发现 \(i,j,k\) 这三维好像没有一维是可以砍掉的,这为我们优化复杂度带来了困难。
考虑去改变我们求最大前缀和的方式。倒序考虑,我们惊讶的发现对于一段后缀,其于整个序列的最大前缀和有贡献的部分即为其最大前缀和!
证明是容易的,考虑到每在前面插入一个数实质上是增加一个前缀和并把所有已有的前缀和加上他的值。
至此我们可以设计出一个状态数是 \(O(n^2)\) 的 dp:设 \(f_{i,j}\) 表示把前 \(i\) 个数填完,当前 \([i+1,n]\) 的最大后缀和为 \(j\) 的期望答案。转移时我们考虑第 \(i+1\) 个数填什么,如果 \(a_{i+1}=1\),则可以以 \(p_{i+1}\) 的系数转移到 \(f_{i+1,\max(j-1,0)}\),否则以 \(q_i\) 的系数转移到 \(f_{i+1,j+1}\)。
如何统计答案?我们发现,对于一段后缀,若其最大前缀和等于 \(0\),则其于答案一定无贡献,则长度为 \(i\) 的答案即为 \(f_{i,0}\)。
这个最大前缀和的转化感觉很有意思,对于一部分题目可以直接砍掉一些复杂度,很有启发意义。
P9479
首先我们考虑 \(m=1\) 的包。我们把原过程转化为向 \(T\) 上插入 \(m\) 个点。那么此时考虑第二个限制,我们一定不能在插入一个节点后,导致任意两个点编号不大于 \(n\) 的点的 lca 改变。更进一步的,我们发现只能把这个点插在一条边上,或把这个点挂在一个已有的点下面当叶子,故此时答案为 \(n+n-1\)。
现在我们考虑一个点可以被插到哪里。
- 插到一条边上。
- 插到一个节点下面做叶子。
- 插到其它地方,并为其钦定一个 \([i+1,i+k]\) 的节点做父亲。
注意到 \(k\) 这一维很小,这启发我们状压后面的 \(k\) 个节点的放置状态。具体而言,设 \(f_{i,S}\) 表示把前 \(i\) 个点填进去,当前第 \([i+1,i+k]\) 的点被钦定的状态为 \(S\) 的方案数。转移考虑按照上面三种分情况讨论。
-
\(i\) 是一个被钦定的父亲。
直接把 \(i\) 填进去即可。
-
\(i\) 不是一个被钦定的父亲。
对于加到边上和叶子上是好求的,具体而言,点数为 \(n+i-1+\text{popcount(S)}\),边数为 \(n+i-1+\text{popcount(S)}-1\),直接以这个系数转移即可。如果说要为 \(i\) 钦定一个父亲,那么直接枚举一个不在 \(S\) 中的数,并将其插到任意一条边上,钦定为 \(i\) 的父亲,改变其状态为已钦定即可。
P4707
这个猛。感觉难点在于想到可以做 Min-Max 容斥,后面 dp 设计状态和拆组合数的那一步也很精彩。
考虑此时的 \(\min(T)\) 的实际含义,那么应该是 \(T\) 中的所有原料出现一种的期望时间,而题目所求即为 \(\min(k,U)\),其中 \(U\) 为全集,稍微转化一下,令 \(k\leftarrow n-k+1\) 变成 \(\max(k,U)\)。
注意到我们实际上是可以快速求 \(\min(T)\) 的,设 \(T=\{a_1,a_2,\cdots,a_t\}\),那么做一次的概率 \(P(\min(T))=\dfrac{\sum\limits_{x\in T} p_x}{m}\),然后得到 \(E(\min(T))=\dfrac{m}{\sum\limits_{x\in T} p_x}\)。
还记得那个式子在期望意义下成立吗?那么我们套上 Min-Max 反演,那么有下面的式子。
考虑 dp。观察原式子中哪些东西需要塞到状态里。注意到一个有趣的事情是对于固定的集合大小,其前面的系数总是固定的,所以我们可以枚举集合大小后把后面那一坨组合数和系数丢到前面,最后乘回去。所以上来有一个 naive 的想法是设 \(f(i,j,k)\) 表示当前考虑到第 \(i\) 个数,\(\vert T\vert=j\),\(\sum\limits_{x\in T} p_x=k\) 的方案数,有转移方程 \(f(i,j,k)=f(i-1,j,k)+f(i-1,j-1,k-p_i)\)。这样得到了一个 \(O(n^2m)\) 的做法。
考虑优化状态。注意到 \(i,k\) 两维必须记录,我们考虑把 \(j\) 压掉,也就是说,我们要对 \(\sum\limits_{T\subseteq U} \dbinom{\vert T\vert-1}{k-1}(-1)^{\vert T\vert-k}\) 这样子的系数求和。
继续考虑转移,延续上面的想法,我们试图构建一个 \(f(i,k)=af(i-1,k)+bf(i-1,k-p_i)\) 式的转移方程。第一部分显然有 \(a=1\),接下来考虑第二部分。
考虑把一个数加入集合以后变成了什么,首先一定会让系数乘上 \(-1\),然后考虑组合数部分,会变成 \(\dbinom{\vert T\vert}{k-1}\)。然后怎么做?\(\dbinom{\vert T\vert-1}{k-1}\rightarrow \dbinom{\vert T\vert}{k-1}\) 这种东西?组合数递推!
那么我们再加一维 \(j\),含义为上面式子中的 \(k\) 是多少(注意不要跟上面的 \(\sum\limits_{x\in T} p_x=k\) 混淆),那么转移即为 \(f(i,j,k)=f(i-1,j,k)-f(i-1,j,k-p_i)+f(i-1,j-1,k-p_i)\)。注意最后那一项两个系数上的 \(-1\) 抵消。
初始状态是 \(f(0,x,0)=[x=0]-1\)。没有明确的意义,实际上可以看作是为了统计答案凑的系数。
P4491
考虑二项式反演。首先考虑钦定 \(i\) 个颜色出现了恰好 \(S\) 次,剩下的颜色任选的方案数,令其为 \(g(i)\),分成两部分考虑,首先考虑没被钦定的颜色,相当于是 \(m-i\) 种颜色随意填到 \(n-iS\) 个空位中,方案数是 \((m-i)^{n-iS}\),然后考虑钦定的颜色,首先要在所有颜色中选择 \(i\) 个,那么是 \(\dbinom{m}{i}\),然后在集合里填上 \(n-iS\) 个占位颜色,那么变成了一个长度为 \(n\) 的可重排列计数,那么方案数是 \(\dfrac{n!}{(S!)^i(n-iS)!}\)。整理一下即可得到 \(g(i)\) 的表达式。
然后考虑二项式反演,设 \(f(i)\) 为恰好 \(i\) 种的方案数。
那么有 \(g(i)=\sum\limits_{j=i} \dbinom{j}{i}f(j)\)。上二项式反演,那么有 \(f(i)=\sum\limits_{j=i}\dbinom{j}{i}(-1)^{j-i}g(j)\)。
拆开组合数,然后合并并化简,即可得到下式。
很明显的卷积形式,对右式 NTT 即可。
P5591
整除下取整我们是不好做的,我们考虑把整除拆掉,\(\lfloor\dfrac{i}{k}\rfloor=\dfrac{i-i\bmod k}{k}\)。
拆掉以后开始化简原式,不难得到下面的式子。
先把 \(\dfrac{1}{k}\) 拿掉,我们观察化简后的式子,分成两部分考虑。注意到第一部分拿掉 \(i\) 以后就是二项式定理,那么考虑把 \(i\) 放进组合数里。有组合恒等式 \(\dbinom{n}{i}i=\dfrac{n!}{(i-1)!(n-i)!}=n\dfrac{(n-1)!}{(i-1)!(n-i)!}=n\dbinom{n-1}{i-1}\),然后回代以后提取系数 \(np\),变成纯正二项式定理。然后考虑第二部分,我们试图将其搞成一个可以单位根反演的形式。
后面的东西显然可以单位根反演,同样拿掉系数,反演后化简可以得到下式。
后面的东西已经和 \(j\) 无关了,再次交换求和顺序把他化到前面去。
换元,令 \(x=\omega_k^{-t}\),那么原问题可以被归约为求解 \(f(k,x)=\sum\limits_{j=0}^{k-1} jx^j\)。这其实是一个经典的等比数列求和形式。
然后把 \((x-1)\) 除过去即可。注意到 \(x\) 是 \(n\) 次单位根,因此一定有 \(x^n=1\)。特判一下 \(x=1\) 即可,即可 \(O(k\log n)\) 解决。