syxqwq

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

计数太差了,加训。

先从简单的开始吧。

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\) 次如下操作:

  1. 每次等概率随机选择一个整数 \(i\),满足 \(1 \leq i \leq n\)
  2. 对所有满足 \(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)\) 计算。

Submission #336123863 - Codeforces

posted on 2025-08-29 22:27  Syxqwq  阅读(11)  评论(1)    收藏  举报