JSOI 选做

[JSOI2018]防御网络

肯定是考虑每条边的贡献,对于每条边,割边和环边的贡献肯定是要分开算的。

对于割边的情况,贡献就是 \((2^{sz}-1)\times (2^{n-sz}-1)\),这类贡献是很好计算的。

考虑不是割边的情况,每个环的贡献肯定是独立的,考虑一个环上的所有点,记录 \(f_i\) 表示第 \(i\) 个点在不经过环边能到达的点中,是否存在被选择的点,\(f_i=1\) 的点会将这个环拆分成若干段,那么一条边会产生贡献当且仅当其在最长的段中。枚举最长区间的左端点和右端点,其余部分直接 \(dp\) 即可。

[JSOI2018]绝地反击

首先考虑一个暴力,二分答案,然后每个节点可以和一段区间内的点配对。不难想到一定存在某个最优解,使得其有一个匹配点在边界上,枚举边界,用二分图匹配来 \(check\),复杂度 \(O(n^{3.5}logM)\)

考虑把所有区间端点按照其膜 \(\dfrac{2\pi}{n}\) 的值排序,考虑相邻两个端点,其网络流建模的差别实际上不太大,只有删去了一些连边在加入一些连边,而每条边最多被加入/删除两次,因此我们只需要支持动态加边删边的二分图最大匹配即可。

加边很好维护,删边的话假设删除的是 \((u, v)\),那么只要跑出一条 \(T\to v\) 的增广路和一条 \((u\to S)\) 的增广路即可。

[JSOI2019]精准预测

首先这是一个显然的 \(2-SAT\) 模型,设 \(f(i, j, 0)\) 表示第 \(i\) 个人第 \(j\) 天死,\(f(i, j, 1)\) 表示第 \(i\) 个人第 \(j\) 天活,那么我们进行如下连边:

\(f(i, j, 0)\to f(i, j - 1, 0), f(i, j, 1)\to f(i, j + 1, 1)\)
对于 \(opt = 0\)\(f(x, t, 0)\to f(y, t+1, 0), f(y,t+1,1)\to f(x, t, 1)\)
对于 \(opt = 1\)\(f(x, t, 1)\to f(y, t, 0), f(t, y, 1)\to f(t, x, 0)\)

对这张图跑缩点,然后 \(Live(i, j)\) 的值为 \(f(i, T+1, 1)\) 能否遍历到 \(f(j, T+1, 0)\),如果可以遍历到则这个值为 \(0\),否则为 \(1\),这样我们就有了一个 \(O(Tn^2)\) 的做法了。

显然有很大一部分点是只当连接作用的,这类点删掉是不受影响的,那么我们只保留每个操作所调用的点,在相邻两个之间连接第一类边,那么点数就降为 \(O(n+m)\),复杂度变为 \(O(n^2)\)

首先将这张图缩点,那么会产生一张 \(DAG\),然后发现这是一个经典的 \(bitset\) 问题,但是空间开不下。有个神奇的操作就是每次只操作 \([B, 2B]\) 里的节点,然后仍然跑 \(bitset\),只需要跑 \(\dfrac{N}{B}\) 轮即可。

[JSOI2019]神经网络

首先经过某个棵树肯定是经过他的一条链,假设将一棵树划分为 \(x\) 条链的方案数为 \(f_x\)。一条路径显然是经过了若干条链,然后把整棵树遍历完成,不难发现只和经过的路径总条数有关,并且这里经过的相邻的两条链不能在同一颗树上。

统计链的方案是一个类似于多重组合数的东西,因此考虑每棵树的 \(EGF\) \(F_i(x)\)。由于要保证相邻互不重复,考虑采用容斥:假设最终方案中有 \(j\) 对链,相邻且颜色相同,那么对答案的贡献就是 \((-1)^j\)。所以在 \(EGF\) 中,枚举每棵树上有多少条链,有多少对是相邻的,那么每棵树的 \(EGF\) 就是:

\[F_i(x)=\sum_i f_i\times i!\sum_{j}(-1)^j\dbinom{i-1}{j}x^{i-j}\dfrac{1}{(i-j)!} \]

将这些 \(EGF\) 相乘即可。但是还有几个问题我们没有解决。

1.怎么保证起点为第 \(1\) 棵树的第一个节点。

我们只需要保证最后一条链不在第一棵树上即可。因为可以通过将包含第一棵树的第一个节点的那条链进行平移,把一号节点以前的部分放在结尾,把一号点以及一号点以后的链放在开头,由于不能算重,所以最后一条链一定不能再第一棵树上。

2.怎么保证包含第一棵树的第一个节点的链在第一个。

那么此时这条链不参与内部排名,也不参与外部排名,直接将系数减一即可。

因此第一条链的 \(EGF\) 为:

\[F_1(x)=\sum_i f_i\times (i-1)!\sum_{j}(-1)^j\dbinom{i-1}{j}x^{i-j-1}\dfrac{1}{(i-j-1)!} \]

至于 \(f_i\) 怎么算,设 \(dp[i][j][0/1/2]\) 表示只考虑 \(i\) 的子树,已经拆分成了 \(j\) 条链,\(i\) 这个点已经拼成了链/单点/长度大于一且只经过了一棵子树。至于为什么要分单点和长度大于一,因为我们对于一条长度大于一的链,贡献需要乘以 \(2\) 的(反向)。分类讨论转移即可。

posted @ 2021-06-08 07:46  呢没理他  阅读(152)  评论(0编辑  收藏  举报