do_while_true

一言(ヒトコト)

AtCoder [2000, 3199] 不水

https://kenkoooo.com/atcoder/#/list/do_while_true?fromDiff=2200&toDiff=3199

abc294h | C

这位真是重量级!感谢 ZCPB 老师教导!

可以用“广义串并联图方法”,即不断删一度点和二度点,来对图进行简化。删完之后一条边有两个权值,分别代表两端颜色相同/不同时这条边对答案乘上的系数。

对于每个连通块单独考虑。如果点数很小,可以直接枚举颜色的最小表示,也就是爆搜一下集合划分。点数很多的话,非树边会比较少,所以就对于每个返祖边的 dep 较小的点组成的集合,搜这个集合里面的点的颜色的最小表示,然后上个暴力树形 dp 算方案数就行。

复杂度不是很会算,但跑得很快!

Code

arc158d | D

这啥???

摸鱼酱一语切中了肯綮!观察到等式左右两侧都是齐次的,那么自然有 \(F(tx,ty,tz)=t^kF(x,y,z)\)

假设左边为 \(F\),右边为 \(G\)\(F(tx,ty,tz)=t^aF(x,y,z),G(tx,ty,tz)=t^bG(x,y,z)\),那么 \(\frac{F(x,y,z)}{G(x,y,z)}=\frac{F(tx,ty,tz)}{G(tx,ty,tz)}t^{b-a}\),想令 \(\frac{F(tx,ty,tz)}{G(tx,ty,tz)}=t^{a-b}\).

\(x,y,z\) 进行随机,直到 \(G(x,y,z)\) 有逆元然后求出 \(t^{-1}\),并且还要 \(t^{-1}\) 能求逆元然后求出 \(t\),就可以了。

arc158e | D

分治,\([l,r]\) 劈成两段 \([l,m],[m+1,r]\),计算跨过 \(m,m+1\) 中间这条线的最短路。对左侧每个格子 \(f_x,g_x\) 分别表示到达 \((1,m)\)\((2,m)\) 的最短路(不会回头所以直接 dp),右侧也类似处理出 \(f,g\) 是到 \((1,m+1),(2,m+1)\),然后考虑两个格子 \(x,y\) 的最短路就是 \(\min(f_x+f_y,g_x+g_y)\),假如是 \(f\) 更优那么就是 \(f_x+f_y<g_x+g_y\Longrightarrow f_x-g_x<g_y-f_y\),那就排序,前缀和,二分。

时间复杂度 \(T(n)=2T(n/2)+\mathcal{O}(n\log n)=\mathcal{O}(n\log^2n)\)

abc293h | D

编一个看起来挺对的 dp:

\(f_x\) 表示 \(x\) 到子树内的颜色的最大颜色数最小是多少;

\(g_x\) 表示 \(x\) 子树内染色之后的答案。

然后考虑 \(f_x\) 的转移是让 \(x\) 和子树中 \(f\) 最大的 \(u,v\) 染同样颜色。考虑 \(g\) ...... 这时候发现问题了。

\(g\) 的转移中 \(f\)\(g\) 的信息都需要。以为既要对 \(f\) chkmax,也要对 \(g\) chkmax.贪心肯定是让两个都尽可能小,但是无法定义它们之间的优先级,究竟优先哪个更小是更优的。这样分开记的话,无法得知究竟应该选哪一对 \((f,g)\),只知道最小的 \(f\) 和最小的 \(g\) 是啥。

一个有点用的观察是直接利用重链剖分构造出答案的上界是 \(\mathcal{O}(\log n)\) 级别的。那么就可以将 \(f,g\) 其中一维记在下标里,然后值域里面存另一维最小值是多少。

另外一个思路是考虑二分答案,这样只需要保证 \(g\) 满足 \(\leq mid\) 即可,然后去 dp \(f\),这样复杂度就是 \(\mathcal{O}(n\log\log n)\) 了。

这个得写下代码才行,青蛙鸽了

arc156d | A

异或有很好的性质,相同直接抵消。那考虑按照将 \(X\) 看成多重集来划分等价类,仅大小为奇数的等价类贡献答案。考虑这个多重集的形态,假设下标 \(i\) 出现了 \(c_i\) 次,那么总的出现次数就是:\(\binom{K}{c_1,c_2,\cdots,c_n}\)(多重集的排列数)

欲求其出现次数奇偶性,考察其 \(2\) 的次幂是否为 \(0\),仿照 Kummer 定理,容易猜出 \(2\) 的次幂为 \(c_1+c_2+\cdots+c_n\) 在二进制下的进位次数,而证明与 Kummer 定理证明几乎一致故略去。那么现在 \(\binom{K}{c_1,c_2,\cdots,c_n}\) 为奇数当且仅当 \(c_1,c_2,\cdots,c_n\) 两两无交。( Lucas 定理?)

也就是将 \(K\) 二进制分解,每个二进制位分配给一个 \(c_i\),这样得出来的 \(c\) 才是会给答案产生贡献的。

那么思路就转到在数位上考虑,观察到 \(N,A\) 都比较小,所以想到设数位 dp \(f_{i,j}\) 表示从低到高考虑到第 \(i\) 位,总和在第 \(i\) 位这里进的位是 \(j\),所有方案的异或是多少。如果这一位是 1 转移就枚举这个 1 分配给哪个 \(A\),然后为了 \(f\) 能够转移还要记一下模 2 下的方案数 \(g\)

注意到 \(j\) 的上界是 \(\sum_{i\geq 1} \lfloor\frac{A}{2^i}\rfloor=\mathcal{O}(A)\),那么时间复杂度是 \(\mathcal{O}(NA\log K)\)

补一下中间那个证明:

\(v_2(n!)=\sum_{i\geq 1}\lfloor\frac{n}{2^i}\rfloor\),令 \(\lfloor\frac{n}{2^i}\rfloor=S_i(n)\)

\(v_2(\frac{n!}{c_1!c_2!\cdots})=\sum_{i\geq 1}S_i(n)-S_i(c_1)-S_i(c_2)-\cdots\)

那么 \(S_i(n)\) 实际意义为 \(n\) 截取最底 \(i\) 个二进制位之后的值。

\(\sum_{j}S_i(c_j)\) 实际为所有 \(c\) 仅看除去最底 \(i\) 个二进制位之后的值再求和。

\(n=\sum_j c_j\),那么 \(S_i(n)-\sum_{j}S_i(c_j)\) 即为“所有 \(c\) 仅看最底 \(i\) 个二进制位求和后再截掉最底 \(i\) 位”,也就是在第 \(i\) 位进了多少位。

agc061c | C

学习一下不容斥的做法

\(f_i\)\([i,n]\) 的答案。然后考虑能不能转移,现在考虑选 \(r\) 的情况:

对于左端点落在 \([l_i,r_i]\) 的区间,枚举这些区间中第一个选 \(r\) 的是哪个区间。如果都选 \(l\) 那么方案数就是 \(f_{p+1}\)\(p\) 是最后一个左端点落在 \([l_i,r_i]\) 的区间编号。

如果枚举了第 \(j\) 个区间是第一个选 \(r\) 的,现在有 \([i+1,j-1]\) 都选的 \(l\)\(i\) 选的是 \(r\),然后考虑 \([j+1,n]\) 的选择方案,首先 \([i+1,j-1]\),但是需要 \(j\) 是选 \(r\) 的,所以记 \(dp_j\)\(j\) 选右端点时 \([j,n]\) 的方案数。然后发现 \(dp_j\) 中的方案,将 \([i,j-1]\) 都插到 ranklist 中得到的方案,与计算 \([i,n]\)\(j\) 是第一个选 \(r\) 的方案,是一一对应的

(不能一一对应的话就是对于一个 \([l,r]\)\(r_i\) 在其中,但是没有其它选了的位置在 \([l,r]\) 中,导致选 \(l\) 还是选 \(r\) 出现了区分。由于题目的特殊性质,\(r_i\)\([l,r]\) 中那么 \(r_j\) 一定也在 \([l,r]\) 中,所以不会出现这种情况)

所以就直接令 \(dp_j\) 转移到 \(f_i\) 就行。\(dp_i\) 的转移是几乎一模一样的。

现在考虑 \(f_i\) 的转移,选 \(l\) 的情况,如果直接算 \(f_{i+1}\) 的话发现会有算重的,而算重的情况就是 \(f_i\)\(r\)\([i+1,p]\) 中的区间都选右的情况,这个就是 \(dp_p\) 了。

后缀和优化就能做到 \(\mathcal{O}(N)\)

abc297h | C

先考虑计数怎么做,容斥一下,钦定若个段内部是相等的。那就 dp,\(f_n=\sum_{i\geq 1}\sum_{j\geq 1}(-1)^{j-1}f_{n-ij}\),处理出 \(a_i\) 使得 \(f_n=\sum_{i=1}^{n-1} a_if_{n-i}\),然后分治 fft 算下就行。

如果要算答案 \(g_n\) 也一样,\(g_n=\sum_{i\geq 1}\sum_{j\geq 1}(-1)^{j-1}(jf_{n-ij}+g_{n-ij})\),再搞个 \(b_i\) 就是 \(g_n=\sum_{i=1}^{n-1}a_ig_{n-i}+\sum_{i=1}^{n-1}b_if_{n-i}\),分治 fft 一起算 \(f\)\(g\) 就行。

时间复杂度 \(\mathcal{O}(n\log^2 n)\)

arc159c | D

为什么这都想不出来/fn 越来越笨了/fn

考虑操作 \(k\) 次那么总和 \(sum\) 变成 \(sum+k\frac{n(n-1)}{2}\),这个需要是 \(n\) 的倍数,先考虑 \(k\) 是偶数的情况。

现在 \(k\) 是偶数有解当且仅当 \(sum\)\(n\) 的倍数。必要显然,充分就开始构造:

首先发现:

第一步:1 2 3 4 5 ... n-1 n;

第二步;n n-1 ... 5 4 3 2 1.

这样子相当于完全没有变化。然后微调一下:

第一步:1 2 3 4 5 ... n-1 n;

第二步;n-1 n ... 5 4 3 2 1.

这样就实现了第一个减去 1,第二个加上 1.那么用这个玩意把所有数都推成平均值即可。

\(k\) 是奇数的话,先随便操作一次,然后变成 \(k\) 是偶数的情况,由于无论第一次怎么操作都不会改变操作后的 sum 具体值,所以随便操作一下然后尝试构造就行。

arc153d | A

套路:考虑第 \(k\) 位是否进位给 \(k+1\),按照最底下 \(k\) 位从大到小排序,能进位的一定是个前缀。那么数位 dp 只需要记当前考虑了前 \(i\) 位,第 \(i\) 位上有 \(j\) 个进位,就能知道哪些进了位,再考虑这一位填啥就行。

arc139d | A

套路:期望可以拆成 \(>x\) 的概率之和,即使是计数问题也一样,\(>x\) 的方案数之和。

然后就考虑 \(>x\) 的有多少个的方案数,加起来就是答案,这个统计就很简单了。假如现在有 \(c\)\(\leq x\),那么每轮就有 \(x\) 种方案 \(c\geq c+1\),有 \((M-x)\) 种方案 \(c\) 不变,然后 \(c\) 再和 \(X-1\) 取 min,按照初始时 \(c\)\(X-1\) 的大小分类讨论,枚举 \(K\) 次操作中有几次是取到 \(\leq x\) 的值即可统计方案数。

abc309h | D

折线容斥的新思路?!

首先是个格路计数问题,尝试反射容斥无果。

每上一层可以往左走或者中间走或者往右走,看上去就很想让答案多项式去乘一个 \((x^{-1}+1+x^1)\),那需要在模 \((x^M-1)\) 意义下做,那么现在问题。。。

posted @ 2023-03-23 22:01  do_while_true  阅读(32)  评论(0编辑  收藏  举报