近期总结2023.10.18
CF1458C Latin Square
题意:一个 \(n\times n\) 的方阵,每行每列都是一个 \(1...n\) 的排列。有 \(m\) 次操作,每次向左/向右循环移动每一行/每一列,或者把每一行/每一列变成逆排列,求操作后的方阵。
\(1\le n\le 1000,\space 1\le m\le 10^5\)
遇到这种毒瘤操作,不能直接做。
考虑将每个数化为 \((x,y,z)\) 的形式,其中 \(a_{x,y}=z\)。
这样可以结合逆排列的本质(即二元组上下交换),这里相当于交换 \(x,z\) 或 \(y,z\)。
一次循环位移相当于给每个三元组的 \(x\) 或 \(y\) 同时 \(+1\) 或 \(-1\)。
这些操作都很好维护,\(O(m+n^2)\)。
Luogu8100 Counting Haybales P
题意:\(n\) 个数,\(a_{1...n}\)。若 \(|a_i-a_{i+1}|=1\),你可以将 \(a_i,a_{i+1}\) 中的较大值减一、较小值加一。
求最终可能得到的序列个数,模 \(10^9+7\)。
\(1\le n\le 5000\)
每次操作相当于把两个差绝对值 \(\le 1\) 的数交换。
不难发现,奇数、偶数的各自的相对顺序永远不变,因为同奇偶的两个数必定不能交换。
把奇数、偶数分出来,设分别有 \(m_1,m_2\) 个。
直接 \(\text{DP}\)。设 \(f[i,j]\) 表示前 \(i\) 个奇数和前 \(j\) 个偶数进行排列的方案数。
转移判一下条件即可,\(O(n^2)\)。
Luogu6846 Amusement Park
题意:一个无向图,把它的若干条边反向,使其形成 \(\text{DAG}\)。求所有方案中,反向的边数之和,模 \(998244353\)。
\(1\le n\le 18\)
把一个 \(\text{DAG}\) 边全部反向,还是 \(\text{DAG}\),那么我们改成 \(\text{DAG}\) 的方案是两两对应的。
因此期望反向 \(\frac m2\) 次,我们只需要求出总方案数即可。求 \(\text{DAG}\) 定向方案数,这应该算是比较板,可惜我不会。
考虑状压,设 \(f[S]\) 表示点集 \(S\) 形成 \(\text{DAG}\) 的方案数。\(\text{DAG}\) 具有分层性质,直接枚举最后一层进行转移。
注意到这并不是明显分层,我们统计的方案数存在重复,容斥即可。\(O(3^n)\)。
CF1737E Ela Goes Hiking
题意:有 \(n\) 只蚂蚁,均匀分布在一条线上,第 \(1\) 只左边和第 \(n\) 只右边有隔板。蚂蚁一开始等概率选择向左或向右走,当有两只蚂蚁相遇时,重量大的吃掉重量小的(重量相等时,右边吃左边),吃完后重量为原来两只蚂蚁的重量之和,然后继续原先的方向行走。当蚂蚁遇到挡板时,回头。求每只蚂蚁存活到最后的概率,模 \(10^9+7\)。
\(1\le n\le 10^6\)
大力手玩题。
第 \(1\) 只蚂蚁只能向右走,第 \(n\) 只蚂蚁只能向左走。第 \(1...n-1\) 只蚂蚁向右必死,只能向左走(即,第 \(1\) 只蚂蚁必死)。
发现,第 \(i(2\le i<i)\) 只蚂蚁,紧挨的左边必须有至少 \(\lfloor \frac {i-1}2 \rfloor\) 只蚂蚁向右走,给他进食。
设 \(j\) 为上一个向左走的蚂蚁,到达一定时间蚂蚁 \(1...j\) 一定会合成一个蚂蚁,我们必须保证 \(j\le i-j\)。
然后 \(i\) 便吃掉了蚂蚁 \(1...i-1\),向右边走,我们还需考虑其吃掉右边所有蚂蚁的概率。
设 \(f[i]\) 表示 \(1...i\) 合并成一个蚂蚁,吃掉右边所有蚂蚁的概率。
手玩一下发现到达一定时间,右边总是若干个向左走的蚂蚁,各有其重量。
转移:
前缀和优化即可,\(O(n)\)。
Luogu5327 语言
题意:一棵树,\(n\) 个点,\(m\) 种语言。你第 \(i\) 次给路径 \(u\rightarrow v\) 上的点教会第 \(i\) 种语言,求最终有多少点对满足存在至少一种共通语言。
\(1\le n,m\le 10^5\)
设 \(S_i\),表示点 \(i\) 与哪些点有共同语言,是一个集合。
每次 \(u\rightarrow v\),相当于对于所有 \(x\in \text{Path}(u,v)\),操作 \(S_x\leftarrow S_x\cup \text{Path}(u,v)\)。
我们只需要求 \(\sum_{i=1}^n |S_i|\)。
每次操作 \(S_x\leftarrow S_x\cup \text{Path}(u,v)\),不难发现 \(\text{Path}(u,v)\) 总是包含 \(x\) 的,这给我们提示,说明 \(S(x)\) 包含的这些路径是连通的。
我们把 \(\text{Path}(u,v)\) 拆成 \(\text{Path}(u,x)\) 和 \(\text{Path}(v,x)\),其实 \(S(x)\) 就是 \(x\) 与这些点形成的链的并。
考虑如何求链并的集合大小,设这些链分别为 \(\text{Path}(x,y_1),\text{Path}(x,y_2),...,\text{Path}(x,y_m)\),考虑异像石,相当于按 \(\text{dfn}\) 排序后求 \(\frac{dis(x,y_1)+dis(y_1,y_2)+...+dis(y_m,x)}2\),由于 \(x\) 一定在 \(\text{Path}(y_1,y_m)\) 上,于是可以把 \(x\) 去掉。
求 \(\text{lca}\) 可以用 \(O(n)\) 方法做。
于是,现在变为:把 \(u\rightarrow v\) 的所有点分别打上 \(u,v\) 链的标记,这样时间复杂度为 \(O(n^2)\)。
考虑差分,在 \(u,v\) 处打上 \(u,v\) 链标记,在 \(\text{fa}(\text{lca}(u,v))\) 处打上两个 \(u,v\) 链撤销标记。
发现可以线段树合并,\(O(n\log n)\)。