2024年08月随便做做
Miscellaneous
Codeforces 1119F - Niyaz and Small Degrees
对于一个固定的度数限制 \(x\),显然有 dp:\(f(u,0/1)\) 表示考虑 \(u\) 以及子树内的点边,是否删除了 \(u\) 连向 \(father_u\) 的边,这时满足限制的最小删边权值和为多少。
假设所有点的度数都大于等于 \(x\),那么 \(f(u,0)\) 的转移应该是先假定所有儿子 \(v\) 都是 \(f(v,0)\),之后再选出若干 \(v\) 加上 \(f(v,1)-f(v,0)\),表示删除这些点,保证删完之后 \(u\) 是满足限制的。
对于度数小于等于 \(x\) 的点,可以挂在父亲上,和 \(f(v,1)-f(v,0)\) 一起算。这个可以使用平衡树做到。
但是对于 \(x\in [0,n-1]\) 我们都要计算答案,是否会超时呢?实际上并不会,用的时间应该是 \(O\sum_{x\in[0,n-1]}\sum_{1\le i\le n} [d_i\ge x])=O(\sum d)=O(n)\)。
所以总的时间复杂度为 \(O(n\log_2 n)\)。
Submission #276341229 - Codeforces
[CCC2019] Tourism
发现显然有如果要让游览到第 \(n\) 个景点的天数最少,那么第 \(i\) 天游览完前 \(p_i\) 个景点,那么一定有游览到第 \(p_i\) 个景区的最少天数为 \(i\),这样我们将原本的 \(n\) 个景点分成了 \(\lceil\frac{n}{k} \rceil\) 段,每段有且仅有一天可以游览到这其中的景点。于是就可以 \(O(n)\) 的转移了。
QOJ #2568. Mountains
记 \(f(i,j)\) 表示在矩阵 \(A\) 上从 \((1,1)\) 走到 \((i,j)\) 的路径元素和最大值。那么发现有 \(f\) 与 \(A\) 构成双射,那么需要统计 \(f\) 的个数。显然 \(f\) 中的所有值都在 \([0,k]\) 中。
而且根据 \(f\) 的转移可知,\(f(i,j)\le x\) 的 \((i,j)\) 一定是从 \((1,1)\) 开始阶梯状排列的,只需要统计在 \(n\times m\) 的矩阵中插入 \(k\) 条轮廓线的方案数即可。这个可以将每条轮廓线向左下平移,转化成求 \(k\) 个起点和终点要求一一对应,每个起点各自到各自的终点的路径之间互不相交的方案数。然后使用 LGV 引理即可。
QOJ #3082. Ascending Matrix
与上题类似,\(a_{r,c}=v\) 的限制可以使用多项式插值解决。
[ZJOI2022] 树
\(f(i,x,y)\) 表示考虑到第 \(i\) 个位置时钦定 \([1,i]\) 中有 \(x\) 个属于 \(T_1\) 的非叶子节点,\([i+1,n]\) 中有 \(y\) 个属于 \(T_2\) 的非叶子节点,这时的方案数。
从 \(i\) 转移到 \(i+1\) 时可以考虑钦定 \(i+1\) 的身份:
钦定 \(i+1\) 是 \(T_1\) 的叶子节点: \(f(i+1,x,y-1)\leftarrow f(i,x,y)\times x\times (y - 1)\)。
钦定 \(i+1\) 是 \(T_2\) 的叶子节点:\(f(i+1,x+1,y)\leftarrow f(i,x,y)\times x\times y\)。
初始化:\(f(1,1,i)=i\)。
求答案:\(F_n=\sum_i f(n-1,i,1)\times i\)。
那么有一个问题是有可能出现 \(\exists i\) 既是 \(T_1\) 的叶子也是 \(T_2\) 的叶子,这种情况会算两遍,因此额外加入一个容斥转移 \(f(i+1,x,y)\leftarrow -2f(i,x,y)\times x\times y\)。
时间复杂度 \(O(n^3)\)。
提交记录 #2135370 - LibreOJ (loj.ac)
[AHOI2022] 山河重整
可以发现一点是,如果要求 \(S\sube \{1,2,\cdots, n\}\) 能够满足可以使用子集元素的和表出 \(1,2,\cdots,n\),那么充要条件是:
证明有很多种,可以简单归纳,或者更简单地通过 \(O(n^2)\) 的 dp 推得。
更进一步,如果有 \(S\) 不满足上述条件,则 \(S\) 第一个不能表出的数应该是最小的 \(i\) 使得 \(i> \sum_{v\in S,v\le i} v\),此时得出 \(S\) 中 \(< i\) 的数一定只能连续表出到 \(i-1\)。
记 \(f(i)\) 表示使用 \(\le i\) 的数,和为 \(i\) 且能表出 \([1,i]\) 中的所有数字的方案个数。那么应该有 \(answer=2^n-\sum_{i=0}^{n-1} 2^{n-i-1} f(i)\)。
剩下就是求出 \(f(i)\) 了。
注意到 \(f(i)\) 实际上就是要求满足上述条件的互异分拆数,那么我们记 \(h(i)\) 表示互异分拆数,那么一定会有 \(f(i)=h(i)-g(i)\),其中 \(g(i)\) 表示不满足上述条件的互异分拆数。根据容斥容易得出 \(g(i)=\sum_{j=0}^{i-1} f(j) \cdot t(i-j,j+2)\),其中 \(t(u,v)\) 表示用大于等于 \(v\) 的各个不同的数字拼出 \(u\) 的方案数。容易发现只有 \(j\le \frac{i}{2}\) 的时候 \(t(i-j,j+2)\) 才可能有值,因此可以类似半在线卷积地根据 \(f(0),\cdots ,f(\lfloor\frac{n}{2}\rfloor)\) 直接求出 \(f(\lfloor\frac{n}{2}\rfloor + 1),\cdots,f(n)\) 的值,递归下去就可以了。
提一句 \(h\) 的计算是类似于 \(O(n\sqrt n)\) 求分拆数的 dp,而 \(g\) 的计算可以类似 \(h\) 的计算,因为如果 \(t(i-j,j+2)\) 选出了 \(k\) 个数,那么可以每个数减去 \((j+2)\),总共减去 \((j+2)k\) 之后再求出这 \(k\) 个数的和为 \(i-j-(j+2)k\) 的方案数,我们可以用求 \(h\) 的方法加上精妙的改动后用来求 \(g\),具体可见代码。
时间复杂度 \(T(n)=O(n\sqrt n) + T(n/2)=O(n\sqrt n)\)。
提交记录 #2135608 - LibreOJ (loj.ac)
[2021-2022 集训队互测] 这是一道集训队胡策题
妙妙妙计数题,这两个月遇到的计数题让我以为我自己根本不会计数。
考虑如果 \(\sum_{i,j} ([a_i=c_{i,j}]+[b_j=c_{i,j}]-[a_i=b_j])=n^2\) 那么一定满足条件。而且显然有 \(\sum_{i,j} ([a_i=c_{i,j}]+[b_j=c_{i,j}]-[a_i=b_j])\le n^2\)。因此只要让这个式子尽量去取到最大值即可。发现 \(\sum_{i,j}[a_i=b_j]=(\sum_{i} a_i)(\sum_{j} b_j)+(n-\sum_{i} a_i)(n-\sum_{j} b_j)\),那么就可以将 \(a\) 和 \(b\) 分离单独处理。
对于每个 \(x=\sum_{i} a_i\),计算出最大的 \(\sum_{i,j}[a_i=c_{i,j}]\),并算出有多少种方案可以得出这个最大值。\(y=\sum_j b_j\) 同理。
然后枚举 \(x,y\) 计算即可。单独计算是 \(O(n)\),但枚举 \(x,y\) 的时间复杂度是 \(O(n^2)\),所以总的时间复杂度为 \(O(n^2)\)。
提交记录 #2135864 - LibreOJ (loj.ac)
[2020-2021 集训队作业] Tour
部分分:\(a_i\ge 0\)。
记 \(c_i=a_{p_i}\),原条件相当于 \(\forall i< n:c_ic_{i+1}\le w\)。
将 \(a\) 按从小到大的顺序排序,显然这不会影响答案。同时建立一个队列 \(q\),执行以下操作直到 \(a\) 被删空:
- 记 \(x\) 为当前 \(a\) 中最小的数,\(y\) 为 \(a\) 中最大的数。
- 如果 \(xy\le w\),则在 \(a\) 中弹出 \(x\) 并在 \(q\) 的末尾加入 \(x\),并将 \(x\) 标记为好的;如果 \(xy>w\),则在 \(a\) 中弹出 \(y\) 并在 \(q\) 的末尾加入 \(y\),并将 \(y\) 标记为坏的。
然后可以按照队列内部的顺序依次将队内元素插入 \(c\) 中,因为无论什么插入顺序只要满足题目要求就可以计数。这时有一个看似显然实则非常非常强大的性质,就是如果当前队首元素为 \(x\),当 \(x\) 为好的时,当前队中的所有元素与 \(x\) 的乘积一定都 \(\le w\);当 \(x\) 为坏的时,当前队中的所有元素与 \(x\) 乘积一定都 \(>x\)。
那么我们在插入时可以记录当前空位数,初始时只有一个空位,此时考虑要插入 \(x\):
- 如果 \(x\) 为好的,那么将 \(x\) 插入任意一个空位之后都会有:它的左右两边在之后都可以插入新的数,而它本身消耗了一个空位数,所以空位数会增加一个。
- 如果 \(x\) 为坏的,那么将 \(x\) 插入任意一个空位之后都会有:它的左右两边在之后都不能插入新的数,而它本身消耗了一个空位数,所以空位数会减少一个。
而插入时任意空位显然是等价的,因此考虑记录空位数即可。
具体的,如果队中第 \(i\) 个元素为好的,则 \(t_i=1\);否则 \(t_i=-1\)。那么答案就是:
主要用到了两个关键(但是显然)的性质:
- 任意插入顺序对答案没有影响。
- 任意数字集合 \(S\),总是存在 \(v\) 使得它和 \(S\) 中任意数的乘积都同时 \(\le w\) 或者 \(>w\)。换句话说,对于是否满足题目的要求,一定存在一个数使得后续的插入均满足或均不满足。
部分分:\(n\le 2000\)。
不妨把 \(0\) 当作正数考虑。
显然一正一负是满足限制的。
因此可以按正负分段,设正数极长连续段个数为 \(i\),负数极长连续段个数为 \(j\),应该有 \(|i-j|\le 1\),这样就做到了正负分离,只需要分别计算正数 \(i\) 段的方案数和负数 \(j\) 段的方案数并乘起来即可。
记 \(F(i)\) 表示正数的极长连续段个数为 \(i\) 时的方案数(负数同理)。我们希望求出这个,但是很困难。一个想法是将上个部分分的初始一个空位改成 \(i\) 个。这样计算出的实际上是至多 \(i\) 个连续段的方案数记为 \(f(i)\),且如果恰有 \(x\) 个极长连续段,则这种方案会在 \(f(i)\) 中被计算 \({i\choose x}\) 次。
那么就有二项式反演: \(f(i)=\sum_{j\le i} {i\choose j} F(j)\Rightarrow F(i)=\sum_{j\le i} (-1)^{i+j}{i\choose j} f(j)\)。
可以 \(O(n^2)\) 求出 \(F\) 和 \(f\)。然后同理求出负数的 \(G\) 和 \(g\),然后枚举 \(f,g\) 来 \(O(n)\) 合并。
如果想要做到可过的时间复杂度,就需要一些多项式科技了。
首先可以知道 \(f(x) = \prod_{i=1}^n(x+\sum_{j=1}^{i-1}t_j)=\prod_{i=1}^n (x+s_i)\),这个可以分治求出,然后多点求值求出 \(f(0),f(1),\cdots,f(n)\) 的值。
发现:
可以得出 \(\mod x^{n+1}\) 意义下的 \((-1)^xF(x)\) 的下降幂多项式的系数,因为此时是下降幂多项式,因此多点求值是好做的。
但是到此为止了吗?
继续观察,发现难写的地方是对于 \(f(x)\) 多点求值,但是如果 \(f(x)\) 是下降幂多项式形式就会很简单,因此我们直接在分治卷积的时候就把 \((x+s_i)\) 当作下降幂多项式,这样进行下降幂多项式乘法就可以快速求出 \(f(0),\cdots,f(n)\) 的值了。
当然常数还是很大,所以我对 \(a_i\ge 0\) 的包进行了单独判断才过了。如果写 4-base 的 NTT 会快很多。
提交记录 #2136325 - LibreOJ (loj.ac)
[2023-2024 集训队互测] 序列
似乎找到等价条件之后就没啥好说的了。
唯一值得一提的是转移式:
其中加号前面的意义,应该简单理解 \(a,b\) 为矩形的长和宽,无论 \(g(i-a,j-b)\) 所包含的情况如何,\(b\) 都是直接搭在前面情况中的最大值上的。
[2022-2023 集训队互测] 六元不定方程
构思题目,思慕出题人,我是杀猫。
首先 \(\mod N\) 是个问题因为 \(N\) 不是质数,但是因为 \(\mu(N)\ne 0\),因此考虑 \(N\) 的标准分解 \(N = p_1p_2\cdots\) ,会发现比较妙的一点是,我们对于每个 \(p_i\) 将其当作 \(N\) 计算出答案之后乘起来就是对于 \(N\) 的答案。换而言之,固定 \(r\) 的情况下,设 \(\mod x\) 的计数答案为 \(f(x)\),则 \(f\) 是一个积性函数。原因在于考虑中国剩余定理,应该会有:
左右是有唯一对应关系的,在 \(p_i\) 中各个不同的 \(r_i\) 会最终组成小于 \(N\) 的唯一的 \(r\),\(r\) 也容易得出唯一的 \(r_i\),显然对于 \(a,b,c,a',b',c'\) 也是如此。
通过 PR 将问题转化成求 \(f(p)\),其中 \(p\) 是质数。最终的答案就是 \(\prod_{i=1}^n f(p_i)\)。
考虑如果固定 \(a,a'\),那么会有多少组 \((b,b')\) 呢?实际上这个答案似乎和 \(r\) 是否为 \(0\) 有关,那么分类讨论。
(i) \(r=0\)。
首先考虑 \((a,a')=(0,0)\) 或者 \((b,b')=(0,0)\) 的情况,经过分讨得出方案数为 \(2p^3+p^2-2p\)。
那么现在就有 \((a,a')\) 和 \((b,b')\) 都不等于 \((0,0)\) 了。
在这种情况下,会有一个神奇的事,就是固定 \((a,a')\ne (0,0)\),那么无论 \((a,a')\) 是什么,\((b,b')\) 都有 \(p-1\) 组解,因为我们已经把全为 \(0\) 的解排除在外了。
然后就得到方程:
有唯一解解当且仅当 \(ab'\ne a'b\)。而其他的情况,上下线性相关,应该有:\((a,a')=k(b,b')\),因为有 \(r=0\),因此 \(k\in[1,p-1]\),此时应该有 \(ka^2+k(a')^2\equiv a^2 + (a')^2 \equiv 0 \mod p\),而 \((c,c')\) 因为 \((a,a')\ne (0,0)\) 而恰好有 \(p\) 组解。
我们记 \(x^2+y^2\equiv r\mod p\) 的解的个数为 \(C_r\)。
那么实际上这部分的方案数应该是:
(ii) \(r>0\)。
这时显然 \((a,a'),(b,b'),(c,c')\) 都不会等于 \((0,0)\)。
固定 \((a,a')\),发现 \((b,b')\) 恰好有 \(p\) 组解。
同样得到方程:
有唯一解当且仅当 \(ab'\ne a'b\)。而其他的情况,因为有 \(r>0\) ,所以应该有 \((a,a')=(b,b')\)。因此就是 \(a^2+(a')^2\equiv r\mod p\),就是 \(C_r\) 了。而此时 \((c,c')\) 有 \(p\) 组解。
而 \(ab'=a'b\) 的情况为了去掉我们仍然要计算,应该有 \((a,a')=k(b,b')\),方案数为 \(\sum_{i=1}^{p-1} C_{r/k}=p^2-C_0\)。
因此这部分总的方案数应该是:
最后就是求 \(C_0,C_r\) 了。
引入勒让德符号 \(\left(\frac{a}{p}\right)\)。
则对于任意 \(b\) 应该有:
那么就有:
带回各部分计算再组合起来,就可以得到答案了。
[PKU-CPC 2023] Empty Up a Bottle
对于 \(A,B,C\),如果对 \(A,B\) 进行操作,则会有 \(A'\equiv 2A \mod (A+B),B' \equiv 2B\mod (A+B)\)。同理 \(\times 2^k\) 的都可以做到。
如果 \(A+B\) 为奇数,一次操作还可以做到 \(\times 2^{-k}\)。
假设有 \(A,B\) 为奇数且 \(A<B\),\(C\) 为偶数。
则可以操作:\((A,B,C)\to (2^kA,B-(2^k-1)A,C)\to (A,B-(2^k-1)A,C +(2^k-1)A)\)。
两次就可以让 \(B\) 至少减少一半,所以只会经过 \(O(\log_2 A + \log_2 B)\) 轮。
Source code - Virtual Judge (vjudge.net)
Atcoder ARC156D - Xor Sum 5
由卢卡斯定理可以简单得到,如果 \(m_i\) 表示 \(i\) 在 \(p_i\) 中出现的次数,那么 \(m\) 对应的所有 \(p\) 总共有对答案的(异或)贡献当且仅当 \(\forall i,j:m_i\& m_j=0\) 并且 \(\sum m =n\)。
然后就可以对答案进行数位 dp,因为 \(a\) 很小,所以直接将值记在状态里。
\(f(i,s)\) 表示考虑到了第 \(i\) 位,第 \(i\) 到 \(i+10\) 位的状态为 \(s\) 时前 \(i-1\) 位所有方案异或的答案,\(g(i,s)\) 表示同样的状态下,这个情况的方案的奇偶性。
转移是简单的。
时间复杂度 \(O(n^2\log_2 k)\)。
Submission #56956048 - AtCoder Regular Contest 156
Atcoder jsc2022 Final F - Share the Recipe
记录 \(S\) 为染黑的点集,并记 \(S\circ T\) 表示点集 \(S\) 和点集 \(T\) 之间的已操作的边的集合。
那么正常的 dp 似乎要用到 \(S,S\circ S,S\circ \bar S,\bar S\circ \bar S\) ,并且都要计入状态。这显然是做不了的。
那么简单的思路就是考虑简化,首先并不需要记录 \(S\),而是只需要记录 \(|S|\),在轮次达到 \(A_i\) 时才考虑具体将 \(i\) 对应到 \(S\) 中的哪个数。
其次,\(S\circ S,\bar S\circ \bar S\) 也只需要记录大小。\(S\circ S\) 是因为本身操作哪条边都不会影响其他的状态,而 \(\bar S\circ \bar S\) 的记录可以效仿上边 \(S\to |S|\) 的优化,只在从 \(\bar S\) 中选择点 \(v\) 加入 \(S\) 时才枚举有几条边与 \(v\) 相连。
最后剩下的就是 \(S\circ \bar S\) 的处理了,发现实际上只需要维护出 \(S\) 关于 \(S\circ \bar S\) 的度数可重集就可以了,而发现此时度数最大为 \(|\bar S|\),共有 \(|S|\) 个点,而 \(|\bar S| + |S|=n\),因此可以使用 \(2^n\) 的折线表示法表示出这个度数可重集。
转移实现借鉴了 zhoukangyang。orzorz。
但是跑得极其慢。
不会分析时间复杂度,\(O(能过)\)。
本文作者:saubguiu
本文链接:https://www.cnblogs.com/imcaigou/p/18363639
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步