计数太差了,加训。
先从简单的开始吧。
P3643 [APIO2016] 划艇
\(n\) 个位置,每个位置可以填 \(a_i \in \{x|x\in[l_i,r_i] \land x=0\}\),要求所有非零数严格递增。求方案数。
\(1 \leq n \leq 500,1 \leq l_i \leq r_i \leq 10^9\)。
Solution
\(O(n^2V)\) 的形式是显然的,设 \(f_{i,j}\) 表示第 \(i\) 个位置填 \(j\) 的方案数,转移式子显然是 \(f_{i,j}=\begin{aligned}\sum_{k=1}^{i-1}\sum_{x=1}^{j-1} f_{k,x}\end{aligned}\)。
但是值域有 \(10^9\) 这么多,肯定要想办法离散化掉。
离散化之后表示的是一段区间,但是这样就不好刻画在相同区间里的大小关系了。
还是定义 \(f_{i,j}\) 表示第 \(i\) 个位置填在 \(I_j\) 这个区间的方案数。
显然只有其他在 \(I_j\) 这个区间内的数会被受到制约,设一共有 \(a\) 个数,可以填的区间长度 \(b\),也可以填 \(0\),要求非零数严格递增。则方案数会有 \(\binom{a+b}{a}\)。
我们还是可以枚举一个从哪里转移来的 \(k\),不难发现在 \((k,i]\) 这个区间里的不能选 \(I_j\) 的数一定填 \(0\),所以只需要记录能选到这个区间的数个数 \(cnt\) 即可。
于是有转移 \(\begin{aligned} f_{i,j}=\sum_{k=1}^{i-1}\sum_{x=1}^{j-1}\binom{len+cnt-1}{cnt} f_{k,x} \end{aligned}\)。
设前缀和 \(g_{i,j}=\begin{aligned} \sum_{x=1}^j f_{i,x} \end{aligned}\)。于是 \(\begin{aligned} f_{i,j}=\sum_{k=1}^{i-1}\binom{len+cnt-1}{cnt} g_{k,j-1} \end{aligned}\)。
这样做就做完了,时间复杂度 \(O(n^3)\)。空间可以继续优化,变成从小到大枚举区间 \(I_j\) 可以滚掉一维。
AT_codefestival_2016_final_f Road of the King
有一个 \(n\) 个点的图,目前一条边都没有。
有一个人在 \(1\) 号点要进行 \(m\) 次移动,终点不必是 \(1\) 号点,假设第 \(i\) 次从 \(u\) 移动到 \(v\),那么在 \(u\) 与 \(v\) 之间连一条有向边。
问有多少种序列能满足:最终 \(n\) 个点组成的图是一个强连通图。答案对 \(10^9+7\) 取模。
Solution
被诈骗了。
首先强连通图等价于,从 \(1\) 开始能到达所有点,且所有点都能到达 \(1\)。
不妨定义 \(f_{i,j,k}\) 表示走了 \(i\) 步到了 \(j\) 个点,有 \(k\) 个点能到达 \(1\)。
然后有个结论是剩下 \(j-k\) 个到达过的点一定是和当前在的这个点在同一个强连通分量里,因为你一但回到 \(1\) 这边就是 \(k=j\) 了。
那么转移只有三种可能,到达一个新的点,回到 \(1\) 所在的强联通分量,回到 \(1\) 不在的强联通分量,随便做。复杂度 \(O(n^3)\)。
Submission #68716666 - CODE FESTIVAL 2016 Final。
AT_arc178_d [ARC178D] Delete Range Mex
给定 \(n,m\) 和一个长度为 \(m\) 的无重复元素的序列 \(a\ (0 \leq a_i < n)\),需要计算长度为 \(n\) 的 \(0 \sim n-1\) 的排列 \(P\) 总数,\(P\) 满足进行若干次删除子区间中的 \(\texttt{mex}\) 值后与 \(a\) 相同。
\(1 \leq m \leq n \leq 500\)。
Solution
如果可以删除某个 \(\texttt{mex}\) 的话,那么 \(< \texttt{mex}\) 的数一定会在原序列出现过,所以删除一定是从大到小的。
删除不好做,我们倒着做改成在 \(a\) 中插入几个数使得它能够变成 \(P\) 的方案数,不难发现这个等价于 \(0\sim n-1\) 中所有数都出现过恰好一次。
相当于我们只能在 \(m+1\) 个位置插入数,所以定义 \(f_{i,j,k}\) 表示我们已经钦定好了 \((i,j)\) 这个区间里面的数只有 \(0 \sim k\) 的数的方案数。
从小到大枚举加入的数,分情况讨论。
-
如果该数出现过
我们记录它出现的位置 \(pos_i\),显然我们必须让他属于 \([pos_i,pos_i+1]\) 这个区间(一个是最右边一个是最左边),所以 \(f_{\min(l,pos_i),\max(r,pos_i+1),i} \gets f_{l,r,i-1}\)。
-
如果该数没出现过
直接枚举它被转移到的区间 \([l,r]\),一定是从 \([l,r]\) 中某个被填好的区间转移来的,分左/右端点转移。
则有 \(\begin{aligned} f_{l,r,i}\gets\sum_{k=l}^r f_{l,k,i-1} \end{aligned}\) 和 \(\begin{aligned} f_{l,r,i}\gets\sum_{k=l}^r f_{k,r,i-1} \end{aligned}\)。可以前缀和优化。
答案是 \(f_{1,m+1,n-1}\),复杂度 \(O(n^3)\)。
Submission #68719269 - AtCoder Regular Contest 178。
P10013 [集训队互测 2023] Tree Topological Order Counting
给定一颗 \(n\) 个点的有根树,\(1\) 是根,记 \(u\) 的父亲是 \(fa_u\)。另给出一长度为 \(n\) 的权值序列 \(b\)。
称一个长度为 \(n\) 的排列 \(a\) 为这颗树的合法拓扑序,当且仅当 \(\forall 2 \le u \le n,a_u > a_{fa_u}\)。
对每个点 \(u\),定义 \(f(u)\) 为,在所有这颗树的合法拓扑序中,\(b_{a_u}\) 之和。
现在对 \(1 \le u \le n\),求 \(f(u) \bmod 10^9+7\)。
\(2 \leq n \leq 5000, 0 \leq b_i \leq 10^9 + 7\)。
Solution
首先,在关于一棵树的拓扑序个数是 \(\frac{n!}{\prod siz_i}\)。
考虑到每个 \(u\) 都要计算 \(b_{a_u}\) 之和,不妨直接定义 \(f_{u,i}\) 表示只考虑子树外的情况 \(a_u=i\) 的方案数。
答案是好计算的,\(\begin{aligned} f(u)=\sum_{i=1}^n b_i \times f_{u,i} \times \binom{n-i}{siz_u-1} \times \frac{siz_u!}{\prod_{v \in subtree_u} siz_v} \end{aligned}\)。
组合数表示分配给 \(u\) 子树节点的拓扑序数字是哪些。
考虑如何转移,显然这个方案数是从父亲那边转移过来的。
\(\begin{aligned} f_{v,i} \gets f_{u,j} \times \binom{n-siz_v-j}{siz_u-siz_v-1} \times \frac{(siz_u-siz_v-1)!}{\prod_{x \in subtree_v \land x \not\in subtree_v\land x\neq u} siz_x } \end{aligned}\)。
这步实际上的意义是给 \(v\) 子树以外的节点分配拓扑序,前面我们已经填好了 \(n-siz_u+1\) 个位置,有 \(j\) 个位置实际上是不能填的(子树节点一定比祖先拓扑序大),在这些位置插入 \(siz_u-siz_v-1\) 个节点。
发现每个 \(f_{v,i}\) 都可以从 \(f_{v,i-1}\) 转移来,前缀和优化一下就做到 \(O(n^2)\) 了。
P10592 BZOJ4361 isn
给出一个长度为 \(n\) 的序列 \(a_1,a_2,\dots a_n\)。如果序列 \(a\) 不是非降的,你必须从中删去一个数。
这一操作将被不断执行,直到 \(A\) 非降为止。求有多少种不同的操作方案。操作方案不同当且仅当删除的顺序或次数不同。答案对 \(10^9+7\) 取模。
\(1\leq n\leq 2\times 10^3\),\(0\leq a_i \leq 2^{31}-1\)。
Solution
我们定义 \(f_{i,j}\) 为 \(i\) 号点结尾,长度为 \(j\) 的非降子序列的个数,\(g_i\) 为 \(\sum_{x=1}^n f_{x,i}\),则每个 \(g_i\) 带来的贡献是 \(g_i \times (n-i)!\)。
显然 \(f\) 的转移是 \(\begin{aligned} f_{i,j}=\sum_{k=1}^{i-1} f_{k,j-1} [a_k\leq a_i]\end{aligned}\)。树状数组计算一下是简单的。
现在问题是碰到非降序列就停止这个限制并不好刻画,考虑容斥。
\(g_i\) 中不合法的统计只可能被 \(g_{i+1}\) 删除任意位置的某个元素得来,所以会多计算 \(g_{i+1} \times (n-i-1)! \times (i+1)\) 的部分。
然后你发现你就做完了。复杂度是 \(O(n^2 \log n)\) 的。
CF1842G Tenzing and Random Operations
Tenzing 将进行 \(m\) 次如下操作:
- 每次等概率随机选择一个整数 \(i\),满足 \(1 \leq i \leq n\)。
- 对所有满足 \(i \leq j \leq n\) 的 \(j\),将 \(a_j\) 赋值为 \(a_j + v\)。
Tenzing 想知道,经过 \(m\) 次操作后,\(\prod_{i=1}^n a_i\) 的期望值是多少,结果对 \(10^9+7\) 取模。
\(1 \leq n \leq 5000, 1 \leq m,v,a_i \leq 10^9\)。
Solution
设操作序列为 \(b\),我们要求 \(E(\prod_{i=1}^n (a_i + \sum_j v[b_j \leq i]))\)。
因为期望可以把 \(E((a+b)(c+d))\) 拆成 \(E(ac)+E(ad)+E(bc)+E(bd)\),所以同理,我们可以把这个期望里的加法全部拆出来,拆成若干个 \(a_i\) 乘上某些 \(E(v[b_j \leq i])\) 的乘积。
我们把每一个 \(E(v[b_j \leq i])\) 的 \(j\) 拉出来单独看,显然如果 \(b_j > i\) 整个答案都是 \(0\),这不是我们想要的。
于是可以设 \(f_{i,j}\) 表示第 \(i\) 个位置,前面选了 \(j\) 个不同的数的期望,如果我第 \(i\) 个位置填前面 \(j\) 个已经选过的 \(b\) 的期望一定是 \(v\),否则将会是 \(\frac{i}{n} \times v\)。当然还有一种选 \(a_i\) 的情况。
于是转移是显然的,一种是填相同的数或 \(a_i\),有 \(f_{i,j}\gets f_{i-1,j} \times (a_i + j \times v)\);另一种是填不同的数,一共有 \(m-j+1\) 个待填,所以有 \(f_{i,j} \gets f_{i-1,j-1} \times (m-j+1) \times \frac{i}{n} \times v\)。
答案显然是 \(\sum_i f_{n,i}\)。总复杂度 \(O(n^2)\)。
Submission #335592574 - Codeforces。
P4492 [HAOI2018] 苹果树
小 C 在自己家的花园里种了一棵苹果树, 树上每个结点都有恰好两个分支. 经过细心的观察, 小 C 发现每一天这棵树都会生长出一个新的结点.
第一天的时候, 果树会长出一个根结点, 以后每一天, 果树会随机选择一个当前树中没有长出过结点 的分支, 然后在这个分支上长出一个新结点, 新结点与分支所属的结点之间连接上一条边.
小 C 定义一棵果树的不便度为树上两两结点之间的距离之和, 两个结点之间 的距离定义为从一个点走到另一个点的路径经过的边数.
现在他非常好奇, 如果 \(N\) 天之后小 G 来他家摘苹果, 这个不便度的期望 \(E\) 是多少. 但是小 C 讨厌分数, 所以他只想知道 \(E \times N !\) 对 \(P\) 取模的结果, 可以证明这是一个整数.
\(1 \leq N \leq 2000, 1 \leq P \leq 10^9 + 7.\)
Solution
简单的。但是始终停留在 \(O(n^3)\),看了题解会了。
发现一条点对答案的贡献实际上是 \((n-siz_u)siz_u\),这启示我们设计有关 \(siz\) 的 dp 方程。
比较自然的想法是,我们定义 \(f_{i,j,k}\) 表示以 \(i\) 为根的子树内,加入到了 \(j\) 个节点,\(siz_i = k\) 的方案数,转移只需要讨论第 \(j\) 个节点加入 \(i\) 子树内或子树外便可做到转移。有初始化 \(f_{i,i,1}=i!\),这是在 \(i\) 之前的生成树个数。
但是我们发现 \(i\) 这一维度大家的转移都是一样的,所以直接消掉 \(i\) 这维。就做到 \(O(n^2)\) 了。
其实还有个大相径庭的说法,可以直接省去 \(O(n^3)\) 的那一步。
我们设 \(f_{i,j}\) 表示加入了 \(i\) 个点后所有子树大小为 \(j\) 的个数。
显然我们可以转移到子树内,\(f_{i+1,j+1} \gets f_{i,j} \times (j+1)\)。子树外也可以,\(f_{i+1,j}\gets f_{i,j} \times (n-j)\)。
注意到当我们加入第 \(i\) 个节点时,子树大小为 \(1\) 的方案数会多出 \(i!\) 种,这是我们新加入一个节点带来的方案数,我们并未考虑到。
两种做法代码一样。
AT_agc060_c [AGC060C] Large Heap
考虑 \((1,2,\cdots,2^N-1)\) 的一个排列 \(P=(P_1,P_2,\cdots,P_{2^N-1})\)。当 \(P\) 满足以下所有条件时,称其为堆式排列:
- \(P_i < P_{2i}\)(\(1 \leq i \leq 2^{N-1}-1\))
- \(P_i < P_{2i+1}\)(\(1 \leq i \leq 2^{N-1}-1\))
给定整数 \(A,B\),令 \(U=2^A,\ V=2^{B+1}-1\)。
从所有堆式排列中等概率随机选取一个,求 \(P_U < P_V\) 的概率对 \(998244353\) 取模的结果。
\(1 \leq A,B \leq N-1,2 \leq N \leq 5000\)。
Solution
容易观察到这实际上是一棵满二叉树,并且满足二叉堆的性质,然后 \(P\) 是它的一个拓扑排序后的结果。
注意到 \(A\) 其实在极左的一条链,\(B\) 在极右的一条链,这两条在除了根节点以外的地方均不相交。
于是可以定义 \(dp_{i,j}\) 表示左链保留了从下往上长度为 \(i\) 的部分,右链保留了从上往下长度为 \(j\) 的部分满足 \(P_A < P_B\) 的方案数。
有转移 \(\begin{aligned}dp_{i,j} = dp_{i-1,j} \times f_{i-1} \times \binom{2^i+2^j-3}{2^i-1}+dp_{i,j-1}\times f_{j-1} \times \binom{2^i+2^j-3}{2^j-1} \end{aligned}\)。
其中 \(f_{i}\) 表示树高为 \(i\) 的满二叉树的拓扑个数。后面组合数表示一共有 \(2^i+2^j-2\) 个权值,给不在选出链上的那一个子树的 \(2^{i-1}\) 个点分配权值,由于 \(i\) 是根,最小的数并不能被取到,所以只剩下了 \(\binom{2^i+2^j-3}{2^i-1}\) 个方案。
考虑 \(f_i\) 怎么计算,由于他是从两棵高度 \(i-1\) 的合并而来,先枚举拓扑序是哪两种,再计算这 \(2^{i}-2\) 个空的分配,所以有 \(\begin{aligned} f_{i}=f_{i-1}^2 \times \binom{2^i-2}{2^{i-1}-1} \end{aligned}\)。
我们所要求的概率 \(p_{i,j}\) 表示为 \(\dfrac{dp_{i,j}}{f_i \times f_j \times \binom{2^i+2^j-2}{2^i-1}}\)。
直接代入 \(dp_{i,j}\) 并化简,\(\begin{aligned} p_{i,j}=p_{i-1,j} \times \dfrac{2^i-1}{2^i+2^j-2} + p_{i,j-1} \times \dfrac{2^j-1}{2^i+2^j-2} \end{aligned}\)。
边界很显然,在没加入 \(A\) 之前一只都有 \(p_{N-A-1,*}=1\)。
复杂度 \(O(n^2 \log n)\),预处理也能做到 \(O(n^2)\)。懒了。
Submission #68859444 - AtCoder Grand Contest 060。
CF1781F Bracket Insertion
Vika 喜欢玩括号序列。今天她想用如下算法生成一个新的括号序列。起初,Vika 的序列是一个空字符串,然后她会重复以下操作 \(n\) 次:
- 在当前括号序列中的某个位置等概率地插入新的括号。如果当前序列长度为 \(k\),那么有 \(k+1\) 个插入位置:第一个括号之前、第一个和第二个括号之间、\(\ldots\)、第 \(k\) 个括号之后。特别地,对于一个空的括号序列,有一个插入位置。
- 以概率 \(p\) 选择字符串
(),或者以概率 \(1-p\) 选择字符串)(,并将其插入到选定的位置。括号序列的长度会增加 \(2\)。
如果一个括号序列可以通过在其中插入字符 + 和 1 得到一个正确的算术表达式,则称其为合法括号序列。例如,(())()、() 和 (()(())) 是合法的,而 )(、(() 和 (()))( 不是合法的。
Vika 想知道她最终得到的括号序列是合法括号序列的概率。模 \(998,244,353\)。
\(1 \leq n \leq 500\)。
Solution
显然第 \(i\) 次操作时会有 \(2i-1\) 个空,所以总方案数 \((2n-1)!!\)。
假设 ( 为 \(1\),) 为 \(-1\),那么一个括号串合法的充要条件是 \(\forall1\leq i \leq len, sum_i \geq 0\)。
再观察在某个位置,加入某个前缀会给 \(sum\) 带来的影响,设插入在 \(x\) 之后。如果是 (),会插入 \(sum_x+1,sum_x\) 这两个数字,如果是 )(,则会插入 \(sum_x-1,sum_x\) 这两个。显然当 \(sum_x=0\) 时后面的操作是不合法的。
考虑根据 \(sum\) 来进行 \(dp\),于是我们定义 \(f_{i,j}\) 表示在 \(sum\) 大小为 \(j\) 的数后面插入长度为 \(2i\) 的合法串的方案数,显然答案是 \(\dfrac{f_{n,0}}{(2n-1)!!}\)。
我们可以枚举 \(j\pm1,j\) 这两个位置被分割到哪里了,当然我们要保证 \(j\) 在 \(j\pm1\) 后面。
转移方程为 \(\begin{aligned}f_{i,j}=\sum_{a=0}^x\sum_{b=0}^{x-a} \binom{x}{a}\binom{x-a}{b} P \times f_{a,j} f_{b,j+1} f_{x-a-b,j} + \sum_{a=0}^x\sum_{b=0}^{x-a} \binom{x}{a}\binom{x-a}{b}(1-P) \times f_{a,j} f_{b,j+1} f_{x-a-b,j} \end{aligned}\)。
上述式子中为方便,令 \(x=i-1\)。组合数表示在 \(x\) 次操作中选取长度分别为 \(a,b\) 的不交的两组进行操作。
显然可以把和 \(b\) 无关的部分提到前面去,\(\begin{aligned}f_{i,j}=\sum_{a=0}^x \binom{x}{a} p \times f_{a,j}\sum_{b=0}^{x-a}\binom{x-a}{b} f_{b,j+1} f_{x-a-b,j} + \sum_{a=0}^x \binom{x}{a} (1-p) \times f_{a,j}\sum_{b=0}^{x-a}\binom{x-a}{b} f_{b,j-1} f_{x-a-b,j} \end{aligned}\)。
发现剩下的部分只关于 \(x-a\) 和 \(b\),于是我们令 \(\begin{aligned} g_{i,j,1/0}=\sum_{b=0}^i \binom{i}{b} f_{b,j\pm1}f_{i-b,j} \end{aligned}\)。\(g_{i,j,0}\) 取 \(j+1\),\(g_{i,j,1}\) 取 \(j-1\)。
\(f\) 变为 \(\begin{aligned}f_{i,j}=\sum_{a=0}^x \binom{x}{a} p \times f_{a,j} g_{x-a,j,0} + [j>0]\sum_{a=0}^x \binom{x}{a} (1-p) \times f_{a,j} g_{x-a,j,1}\end{aligned}\)。于是可以 \(O(n^3)\) 计算。
浙公网安备 33010602011771号