做题记录节选

目录

做题记录节选

2020年是之前写的东西,2021年及以后用来记录一些做过的有意思的题目。

2021-5-4

洛谷P5369 [PKUSC2018]最大前缀和

考虑什么样的一个前缀和最大,不难发现当且仅当这个前缀的所有真后缀之和大于等于 \(0\) ,去掉这个前缀后的序列的所有前缀之和小于 \(0\) ,设 \(f_s\) 表示 \(s\) 中所有数组成的序列所有后缀和大于等于 \(0\) 的方案数, \(g_s\) 表示 \(s\) 中所有数组成的序列所有前缀和小于 \(0\) 的方案数,这两个都可以 \(\mathcal O(2^nn)\) dp 求出来,然后就可以统计出每一个集合成为最大前缀和的方案数,乘以权值加起来就行了。

2021-4-21

ARC072C Alice in linear land

可以先模拟一遍求出每个时刻操作前距目的地的距离。

因为可以任意变化,某一个时刻的答案为 NO 当且仅当小于等于当且距离小于等于所在距离全部都可以通过后面的操作到达目的地。

倒推出最大的满足小于等于这个距离都可以到达目的地的值是多少,假如在后 \(k\) 步操作中值为 \(x\) ,后第 \(k+1\) 步操作走了距离 \(d\) ,那么 \([d,d+x]\) 显然满足条件,同时 \([0,x]\)\([d-x,d]\) 也是可行的,这三个区间可以拼成连续的当且仅当 \(d-x\le x+1\)\(x\ge \frac{1}{2}(d-1)\) ,所以就是说当 \(x\ge \frac{1}{2}(d-1)\) 时令 \(x\gets x+d\) 即可。

2021-4-1

CF1404D Game of Pairs

Koishi Loves Construction 一样,上来先考虑求和, \(1\sim 2n\) 的和是 \(\frac{2n(2n+1)}{2}=n(2n+1)\equiv n\pmod {2n}\) ,这也就是说如果后手取到的和是 \(n\) 可以通过取反操作得到和为 \(0\) 的构造方法。

\(1\sim n\) 的和是 \(\frac{n(n+1)}{2}\)

\(n\) 是偶数的时候, \(\frac{n(n+1)}{2}\equiv \frac{n}{2}\pmod {n}\) ,在 \(\mod n\) 的意义下都不等于 \(0\) ,所以显然不能通过加减若干 \(n\) 使得这个数字在 \(\mod 2n\) 意义下等于 0 ,所以先手 \(i\)\(n+i\) 配对后手肯定输。

\(n\) 是奇数的时候, \(\frac{n(n+1)}{2}=\frac{n+1}{2}n\) ,注意到特殊的配对方式,把 \(i\)\(i+n\) 认为是同一个点,点的配对视为连边,那么一个点度数恰好为 2 ,所以必然可以形成若干个环,由此无论先手如何配对,都可以较容易地构造出一个选择方案,使得选择的第 \(i\) 个数要么是 \(i\) 要么是 \(i+n\) ,最后得到的和要么是 \(0\) 要么是 \(n\) ,如果是 \(n\) 取反即可。

2021-3-30

CF1392E Omkar and Duck

可能是挺常用的技巧?题解链接

CF750F New Year and Finding Roots

任意找到一个点 dfs 两个方向取中点就可以找到最高点,从最高点一直向上跳,估计一下大概是深度大于等于某个值的时候通过 dfs 确定找的方向是否正确,深度小于某个值的时候通过 bfs 找根,最坏情况是一开始找到叶子,通过 dfs 确定 4 层的话消耗次数是 \(1+2+3+4=10\) ,最后三层通过 bfs 消耗次数是 \(7\) 的,但是其实没有必要 \(7\) 次用完,如果 \(6\) 次没有找到答案就是剩下的那个点了,所以只需要 \(16\) 次就可以 finding roots 了。

2021-3-29

CF1205C Palindromic Paths

网格图黑白染色,相邻的相同颜色的格子之间的关系可以直接询问得到,由于 \(n\) 是奇数,并且只知道左上角和右下角的数字,所以有一部分格子不知道绝对数字只知道两两间的相对数字,关键是如何确定这些数字。

我搞了好久的分类讨论,由于太复杂就不贴了,讲一讲你古题解里面的做法。

如果存在一条路径 \(p_1,p_2,p_3,p_4\) 满足 \(p_1\oplus p_2\oplus p_3\oplus p_4=0\) 那么 \(p_1=p_4\) 等价于 \(p_1,p_2,p_3,p_4\) 是回文路径,由于左上角是 1 右下角是 0 ,所以必然存在 \(x\) 满足 \(a_{x,x}=1,a_{x+2,x+2}=0\) ,此时这两条路径的异或值:

\[a_{x,x}\oplus a_{x+1,x}\oplus a_{x+1,x+1}\oplus a_{x+2,x+1} \]

\[a_{x+1,x}\oplus a_{x+1,x+1}\oplus a_{x+2,x+1}\oplus a_{x+2,x+2} \]

不同,所以一定存在一个异或为 0 的路径,然后依次询问就可以确定答案了。

CF1174F Ehab and the Big Finale

先问到根的距离,建出到根距离为查询得到的答案的点的虚树,那么答案一定在叶子上面,然后重链剖分,从根一直跳重儿子跳到底端,问距离就可以知道答案在重链的那个点往下走,然后使用 s 操作往下走一步,这样就删掉了一个重子树,通过两次将点数缩小为至少 1/2 ,可以过。

Dandandan 有一个更强的做法,分类讨论,如果没有儿子子树大小大于 1/2 直接向下跳,否则重链剖分,从根一直跳重儿子跳到底端,问距离就可以知道答案在重链的那个点往下走,然后不使用 s 操作直接删掉重儿子把那个点作为下次询问直接递归即可,极端情况下是 1 次减小一半或者 2 次减小 2/3 ,次数大概是 \(2\log_3n\) 级别的?反正吊打我就对了。

2021-3-19

CF521D Shop

显然乘法操作很容易贪心,如果要用加法操作,某一个位置的加法操作肯定从大到小进行,也就是说加法操作的进行顺序是固定的,所以其实每次加法操作也可以理解为一个乘法操作,考虑赋值操作肯定只有一次有用,所以每个位置肯定找最大的赋值操作保留,赋值操作一开始放如果有增加的话相当于是一次加法操作,于是就可以直接从大到小贪心了。

需要注意的就是赋值操作如果选了一定要一开始放。

AGC023D Go Home

假设公交车一开始停在最靠边的两栋楼中间,正难则反,考虑最靠边的两栋楼,不难发现如果最左边人数大于等于右边,那么经过最左边一定先于经过最右边,此时达到最右边的楼的时间一定是到达最左边的楼的时间加上它们的距离,所以此时最右边的人的目的就变成最小化到最左边的楼的时间了,和最左边的人的目的相同,所以可以理解为把它们赶到最左边的楼里面去,如果最左边人数小于右边也是类似的,然后往下递归/循环即可。

2021-3-9

CF436E Cardboard Box

考虑贪心,将所有关卡按照 \(b_i\) 排序,那么如果第 \(i\) 个关卡拿了两颗星那么前 \(i-1\) 个关卡一定至少都拿了一颗星(否则选前面某个关卡拿两颗星更优),所以必然存在一个 \(k\) 满足前 \(k\) 个关卡都拿过星,并且后面的关卡最多都只拿过一颗星,如果枚举这个 \(k\) 那么就可以贪心地求解答案了,动态维护答案用个优先队列之类地就比较好维护了。

2021-3-6

CF715E Complete the Permutations

如果排列 \(p,q\) 给定,那么使 \(p\) 变成 \(q\) 需要的最少次数可以这样来求解:构建一张 \(n\) 个点的图, \(p_i\)\(q_i\) 连边,这样必然会形成若干个环,最少交换次数就是 \(n\) 减去环的数量。由此题目本质就是要让你求形成环的数量为 \(i\) 的方案数。

虽说 \(p,q\) 并没有完全补齐,不过还是类似上面的做法,让 \(p_i\)\(q_i\) 连边,这样会得到五种不同的形态:数形成的环(记作 A )、起点为数终点为数的链( B )、起点为数终点为 0 的链( C )、起点为 0 终点为数的链( D )、起点为 0 终点为 0 的链( E )。 A 可以不用管了,关键是把没有确定的链拼成若干个环。

考虑 C ,这种链显然不会和 D 接在一起,这种链可能的接法其实只有两种,一种是 ECCC...CCCB ,另一种是自己形成环,可以把接在 E 后面的 C 和 E 绑在一起是做一个 E ,所以对于 C 只关心它自己形成了多少个环,对于 D 同理,可以把 C 和 D 使用背包合并起来,剩下的就只有 B 和 E 了,这两个形成环还是很好处理的,然后再使用背包合并起来就可以求答案了,时间复杂度 \(\mathcal O(n^2)\)

2021-3-3

CF1446C Xor Tree

看到异或首先想到 Trie ,从 Trie 的根结点从上往下考虑,如果当前结点两个孩子的 size 都大于等于 2 ,那么这两个孩子肯定是单独形成两个连通块,要形成一棵树必须要让它们连通,所以肯定是把某个孩子里面的数删得只剩一个,这样就可以递归求解了。


下面是之前写的一句话题解里面的东西。

标题用了夸张的修辞,不要在意。

感觉都要变成做题记录了。

好的,其实它就是做题记录,并非所有题目都会写在上面

注意:可能不是实时更新,毕竟这人肯定是个鸽子。

下面的日期写的是 \(\rm AC\) 时间。

咕咕咕


2020-6-11

[十二省联考2019]骗分过样例

题面:

\[1.\texttt{1_998244353} \]

\(T\) 组数据,每次给定一个数 \(x\) ,求 \(19^x\bmod 998244353\)

快速幂+扩展欧拉定理。

复习一下扩展欧拉定理:

\[a^b\equiv\begin{cases}a^{b\bmod\varphi(p)+\varphi(p)}&\ b\le\varphi(p)\\ a^{b\bmod\varphi(p)}&\ b<\varphi(p)\end{cases}\pmod {p} \]

\[2.\texttt{1?} \]

\(T\) 组数据,每次给定一个数 \(x\) ,求 \(19^x\bmod\) 某个数的值。

如何求这个数?找到答案中最大值 \(1145099\) ,从其开始枚举,每次检验一下前几个数是否合法,程序运行得到,模数就是 \(1145141\) ,然后用之前做法即。

\[3.\texttt{1?+} \]

\(T\) 组数据,每次给定一个数 \(x\) ,求 \(19^x\bmod\) 某个数的值。

模数较大,先把所有询问和答案配对,看有没有挨得比较近的询问,发现有以下两个询问和答案接近:

询问 答案
264708066 1996649514996338529
264708068 1589589654696467295

\(1996649514996338529\times 19\times 19-1589589654696467295=719200885258981741674\) ,分解一下这个数,得到 \(719200885258981741674=2\times3\times 23\times 5211600617818708273\) ,显然模数就是 \(5211600617818708273\) ,注意一下这个数的两倍会爆long long,用 \(\mathcal O(1)\) 快速乘或者是unsigned long long加龟速乘。

\[4.\texttt{1wa\_998244353} \]

\(T\) 组数据,每次给定一个数 \(x\) ,求暴力求 \(19^x\bmod 998244353\) 导致爆int后的值(即一直执行x=x*19%998244353,其中x的变量类型为int)。

先用map找到循环节,然后利用循环节求答案。

\[5.\texttt{2p} \]

\(T\) 组数据,每次求 \([L,R]\) 中的每个数是否是质数。

最大的数据范围点是 \([999999999999000000,1000000000000000000]\) ,先筛出所有 \(\sqrt{n}\) 再筛显然过不去,考虑直接枚举每个数用 \(\rm Miller\_Rabin\) 判断即可(顺便借此机会复习一下 \(\rm Miller\_Rabin\) )。

\[6.\texttt{2u} \]

\(T\) 组数据,每次求 \([L,R]\) 中的每个数的莫比乌斯函数。

最大的数据范围点是 \([999999999999000000,1000000000000000000]\) ,如何筛呢?先筛出 \([1,1000000]\) 内的质数,用这些质数去筛掉这部分内的数,然后筛后有四种情况:为 \(1\) 、为一个质数、为两个不相等质数的乘积、为两个相等质数的乘积。 \(1\) 判掉,质数用 \(\rm Miller\_Rabin\) ,相等质数乘积用 \(sqrt()\) 函数即可判断。

\[7.\texttt{2g} \]

\(T\) 组数据,每次求 \([L,R]\) 中每个数是否是给定质数 \(p\) 的原根。

\(p=998244353\) 时暴力判断原根即可,原根判断方法:一个数 \(x\) 是质数 \(p\) 的原根,当且仅当对于 \(\varphi(p)=p-1\) 的任意质因数 \(q\) ,都满足 \(x^{\frac{\varphi(p)=p-1}{q}}\bmod p\ne 1\)

\(p=13123111\) 时要用一种特殊的方法做,引用题解里面的话:

首先,我们暴力找出其最小的一个原根(实际上任意一个原根都可以)。

接下来求出每个数以这个最小原根为原根的指标(即离散对数)。

然后判断每个数的指标与 \(\varphi(p)\) (即 \(p-1\) )是否互质即可判断这个数是否为原根。

但判互质这里需要一种类似于筛的东西。

考虑和上个点一样先求出 \(p-1\) 的全部质因数,然后把这些质因数的倍数全部打个标记。

最后指标没被打标记的就是原根。

\[8.\texttt{2g?} \]

\(T\) 组数据,每次求 \([L,R]\) 中每个数是否是给定质数 \(p\) 的原根(其中有一个 \(p\) 需要猜)。

还是引用题解原话:

考虑出题人会怎么卡你?肯定是把模数放在靠中间的位置。

因此,我们就从中间向两边枚举!

然后对于枚举到的数如何判断呢?

首先依然是 \(\rm MillerRabin\) 判素数。

接下来,我们只验证前 \(50\) 个答案,如果这个数的 \(\frac{p-1}{2}\) 此房为 \(1\) 但是这一位应该是原根,就说明 \(p\) 不是要求的模数。

找到模数为: \(1515343657\)

直接用 \(998244353\) 的暴力判断方法即可。

[十二省联考2019]春节十二响

先考虑简单情况,假设只有一个根节点 \(1\) ,然后根节点连出去了两条链该如何去做,可以把两条链排个序,然后大的值和大的值合并,小的值和小的值合并,不难发现,这样是最优的。

扩展到多叉,每次一样地考虑将代表点 \(u\) 子树的集合和代表其儿子 \(v\) 子树的集合用如此方法合并。

不难发现代表以每个点为根的子树的集合中的元素数量就是最长链,用长链剖分的思想, \(\mathcal O(1)\) 继承重儿子信息,然后合并其他轻儿子,关键在于这个“集合”要如何实现,可以用数组,但是合并完所有信息后还要将当前点的值加入,于是复杂度就过不去了,最好应该是用堆,合并时一个个 \(\rm pop\) 掉即可,加值也很方便。


2020-6-10

[十二省联考2019]异或粽子

前缀异或和后就变成了:任意选择两个数,求他们异或起来的前 \(k\) 大值。

超级钢琴的思路,设 \((x,l,r)\) 表示在 \([l,r]\) 中可以任选一个数和 \(x\) 异或后得到的值的集合,那么肯定会先选最大的,设 \(k\in [l,r]\) 满足 \(a_x\oplus a_k\) 最大,那么从大往小考虑时必然会先选择 \(a_x\oplus a_k\) ,然后将其拆分为 \((x,l,k-1)\)\((x,k+1,r)\) ,至于如何求 \(k\in [l,r]\) ,可持久化Tire即可实现。

这题好像有复杂度更优的算法,据说和 \(k\) 无关,暂且没有学习,加强版是:CF241B Friends,同样的,这题也很类似:CF1055F Tree and XOR,以后有时间可以做做。

[九省联考2018]IIIDX

首先建树,规定 \(i\) 号点的父亲是 \(\lfloor \frac{i}{k} \rfloor\)

如果 \(d_i\) 互不相同,从根节点开始贪心,从小到大地考虑每一个儿子,每次都是选最大的一部分给这个儿子(设这个儿子大小为 \(s\) ,那么把最大的 \(s\)\(d_i\) 都分配给这个儿子及其子树),同时递归下去即可得到答案。

\(d_i\) 存在相同的情况,那么就不可以这么贪心了,举个例子:设最大的 \(s\)\(d_i\)\(\{6,7,8\}\) ,但是由于 \(6\) 可能存在多的,那么说不定分给这个儿子 \(\{6,6,7\}\) 还要更好些,它的兄弟选择的优先级是比它子树里除它外的所有节点要大的!

那么如何处理呢?假设当前能选的数为 \(\{6,6,7,8\}\) ,一个子树的大小为 \(3\) ,那么我们肯定会选择 \(\{6,6,7\}\) ,还是原来的那个原因:它的兄弟选择的优先级是比它子树里除它外的所有节点要大,必须要尽可能为它的兄弟预留空间。

具体实现如下:

先将 \(d\) 从小到大排序去重,统计每个值出现次数 \(cnt(x)\) ,对每个值统计一个 \(f(x)\) 表示大于等于 \(x\) 还没被取的值的个数。

假设给某个节点匹配到了一个值 \(x\) ,那么比小于等于 \(x\) 的值 \(y\)\(f(y)\) 都会减小这个节点代表的子树大小那么多,但是这样做的话大于 \(x\) 的值的 \(f\) 就没有更新,由于有若 \(x>y\) ,那么 \(f(x)\le f(y)\) ,所以我们不妨规定实际上 \(x\)\(f\) 值为 \(\min_{i=1}^xf(i)\) ,不难发现,这样规定是对的。

每次选值的时候就在线段树上二分找到满足在剩下的数中最靠右的并且 $\min_{i=1}^kf(i)\le $ 子树大小的 \(k\) ,然后将区间 \([1,k]\) 执行减去子树大小的操作。

注意:在选取某个节点的值时,必须消去其父亲对除它自己外所有 \(f\) 值的影响,即执行区间加父亲子树大小的操作,引用一篇题解里的话:

想象一下,如果不撤销父亲的影响的话,岂不是相当于别人特意给你占了座,结果你自己还不能坐上去?

因为一个节点的儿子都是连续的,所以我们在撤销的父亲的影响后,会马上把不应该撤销的部分给补上(儿子的子树在不断的加上来),所以不用担心对之后的决策造成影响

[九省联考2018]一双木棋chess

这题主要考的就是状态设置,如果设十维状态肯定不行, \(10^{10}\) 直接爆空间,不难发现十维状态之间是有一定关系的,即后面的数字一定小于等于前面的数字,不妨设 \(f(i,j)\) 表示有 \(i\) 个非负数字,第一个数字为 \(j\) ,后面的数字需满足小于前面的数字的方案数,这样的话就可以利用 \(f\) 来记录状态,将十个数字压倒一个数字里面表示,就可以转移了。


2020-6-7

[六省联考2017]寿司餐厅

最大权闭合子图模型。

将每个 \(d_{i,j}\) 视为一种物品,那么如果拿了物品 \(d_{i,j}\) ,若 \(i\ne j\) ,说明一定要拿物品 \(d_{i+1,j}\) 以及 \(d_{i,j-1}\) ,如果拿了物品 \(d_{i,i}\) ,说明选择了 \(i\) 号寿司吃,一定会花费 \(a_i\) 元(因为付钱数量为 \(mx^2+cx\) ,若选择了 \(i\) 号寿司, \(c\) 就一定会加一),如何表达 \(mx^2\) 呢?显然可以加上 \(\max(a_i)\) 个物品,第 \(i\) 个物品花费为 \(mi^2\) ,若选了 \(d_{i,i}\) ,那么就必须选这其中的第 \(a_i\) 个物品。

建模后直接跑网络流即可。


2020-6-6

上帝与集合的正确用法

写这题是因为想去写相逢是问候,但是这题太难的,还没去写。

扩展欧拉定理得到:

\[a^b\equiv\begin{cases}a^{b \bmod \varphi(p)+\varphi(p)}&\ b\ge\varphi(p)\\ a^b&\ b<\varphi(p)\end{cases}\pmod {p} \]

所以有:

\[2^{2^{2^{\dots}}}\equiv 2^{2^{2^{\dots}}\bmod \varphi(p)+\varphi(p)} \pmod {p} \]

递归下去即可得到答案。


2020-6-5

[六省联考2017]分手是祝愿

不妨把每个开关看做是一个长度为 \(n\) 的二进制数,若按这个开过灯 \(i\) 会改变,那么这个数的第 \(i\) 位就是 \(1\) ,否则是 \(0\)

这样的话多次按开关就相当于是二进制数之间的异或,考虑将这些数一个个插入线性基里,不难发现,全部都会插入成功,因为这些数之间是线性无关的,每个数都有着独一无二的最高位。

既然如此,如果每个开关最多按一次那么要将所有灯熄灭只有一种方法,两次按同一个开关相当于没按,题目转化为:

给定 \(n\) 个开关,其中有 \(m\) 个开关要按奇数次,若剩余开关还需要按的次数少于 \(k\) ,那么就会直接按那 \(k\) 个开关,否则随机一个开关按,问完成任务按开关的期望次数。

\(dp(i)\) 表示还有 \(i\) 个开关要按的最终的期望次数,转移:

\[dp(i)=\begin{cases}i&\ (i\le k)\\ \frac{i}{n}dp(i-1)+\frac{n-i}{n}dp(i+1)+1&\ (i>k)\end{cases} \]

显然直接高斯消元过不了,考虑 \(\mathcal O(n)\) 做。

观察到有: \(dp(n)=dp(n-1)+1\) ,不妨设 \(dp(i+1)=a_idp(i)+b_i\) ,那么由原转移方程可以得到:

\[dp(i)=\frac{i}{n}dp(i-1)+\frac{n-i}{n}dp(i+1)+1 \]

\[dp(i)=\frac{i}{n}dp(i-1)+\frac{n-i}{n}(a_idp(i)+b_i)+1 \]

\[(1-\frac{n-i}{n}a_i)dp(i)=\frac{i}{n}dp(i-1)+\frac{n-i}{n}b_i+1 \]

\[dp(i)=\frac{i}{n}\div (1-\frac{n-i}{n}a_i)dp(i-1)+(\frac{n-i}{n}b_i+1)\div (1-\frac{n-i}{n}a_i) \]

归纳法得出 \(a_i=1\) ,直接去掉 \(a_i\) 即可得到:

\[dp(i)=dp(i-1)+\frac{n-i}{i}b_i+\frac{n}{i} \]

其中 \(b_{n-1}=1\)

由此可以得到:

\[dp(k+1)=\frac{k+1}{n}dp(k)+\frac{n-k-1}{n}(dp(k+1)+b_{k+1})+1 \]

\[\frac{k+1}{n}dp(k+1)=\frac{k+1}{n}k+\frac{n-k-1}{n}b_{k+1}+1 \]

\[dp(k+1)=k+\frac{n-k-1}{k+1}b_{k+1}+\frac{n}{k+1} \]

至此,得到了 \(\mathcal O(n)\)\(dp(x)\) 的方法,至于求哪些开关是要按的,就用类似线性基的方法,开关编号从大往小扫,如果再扫到第 \(i\) 个开关时,第 \(i\) 盏灯还是亮的,就要按第 \(i\) 个开关,改变所有 \(i\) 的因子的灯的情况。

[六省联考2017]摧毁“树状图”

不妨按树上两条路径的相对情况来分类讨论:

情况一:两条路径存在点重合。

因为树上两个点之间只有一条路径,所以如果有点重合,那么一定只会有一个点是公共点,我们可以把这一个点单独拎出来作为根,不难发现所谓的两条路径可以视为 \(1\sim 4\) 条链,其中链的一端就是根,只需要记录从根连出去的前四大链即可得到这种情况的答案。

情况二:两条路径不存在点重合。

不难发现必然存在一棵子树使得一条路径完全在这棵子树内而另外一条路径和这个子树没有交点,考虑枚举每一棵子树,规定这棵子树内的路径经过子树的根,然后找到在这棵子树内的最优路径和子树外的最优路径。

不难发现,上面列出来所要求的都可以通过换根较容易地求出。

状态如下(以下所说的路径及链都可以退化为单点):

\(mx(u,k)\) 表示考虑在以 \(u\) 为根的子树中,对于所有 \(u\) 的儿子 \(v\)\(dp(v)\)\(k+1\) 大的值。

\(cnt(u)\) 表示 \(u\) 的儿子数量。

\(dp(u)\) 表示考虑在以 \(u\) 为根的子树中,去掉以 \(u\) 为一个端点的链后剩下的联通块数量的最大值。

\(fp(u)\) 表示考虑在以 \(u\) 为根的子树中,去掉经过 \(u\) 点的某条路径后剩下的联通块数量的最大值。

\(f(u)\) 表示考虑在以 \(u\) 为根的子树中,去掉某条路径后剩下的联通块数量的最大值。

转移如下:

\[dp(u)=\max(cnt(u),mx(u,0)+cnt(u)-1) \]

\[fp(u)=\max(dp(u),mx(u,0)+mx(u,1)+cnt(u)-2) \]

发现 \(f(u)\) 可能不太好转移,因为对于 \(u\) 的儿子 \(v\) 里面的一条路径,如果是经过 \(v\) 点的话,只考虑以 \(v\) 为根的子树是不会考虑到 \(v\) 外面连着的 \(u\) 所在的连通块造成的贡献,而如果不经过 \(v\) 点的话, \(u\) 所在的连通块是不会造成贡献的,所以考虑多记录点东西:

\(f_0(u)\) 表示考虑在以 \(u\) 为根的子树中,去掉某条路径后剩下的联通块数量的最大值;设 \(f_1(u)\) 表示认为删去 \(u\) 点后 \(u\) 外面还有一个连通块,去掉某条路径后剩下的连通块数量的最大值。

然后我们再假设 \(fmx(u)\) 表示对于所有 \(u\) 的儿子 \(v\)\(f_1(v)\) 的最大值。

转移就比较容易了:

\[f_0(u)=\max(fmx(u),fp(u)) \]

\[f_1(u)=\max(fmx(u),fp(u)+1) \]

好的,看看我们转移用到了哪些东西: \(fmx(u)\)\(mx(u,0)\) 以及 \(mx(u,0)+mx(u,1)\)

显然,换根的时候只要记录: \(fmx(u)\) 的最大次大, \(mx(u,0)\) 的最大次大次次大。

不难发现,更新答案的时候要用到 \(mx(u,0\sim 3)\) ,所以 \(mx(u,0)\) 其实要记录前四大。

[六省联考2017]期末考试

发现当出成绩的最晚时间确定时,学生和老师的不愉快度都是很好算的,当出成绩的最晚时间减一时,很容易就可以维护学生的不愉快度和老师的不愉快度,需要维护这些东西:可以推迟公布成绩的课程总和,需要提前公布成绩的课程总和,学生不愉快度的总和。利用前缀和等操作即可维护,然后从大往小枚举出成绩的最晚时间。


2020-5-29

[APIO2014]连珠线

用来学习换根dp的一道题。

首先转化题意,两个操作可以转化为:

  1. \(\rm Append(w, v)\) :一个新的珠子 \(w\) 和一个已经添加的珠子 \(v\) 用红线连接起来。
  2. \(\rm Insert(w, u, v)\) :一个新的珠子 \(v\) 和一个已经添加的珠子 \(v\) 用蓝线连接起来,同时一个新的珠子 \(w\)\(v\) 用蓝线连接起来。

如果确定了刚开始拥有的点将其作为根,那么题意再次转化:

给定一棵有根树,每次可以选择依次相连的三个深度依次递增的点,并删去连接着这三个点的两条边,执行若干次后,最终被删除的边边权和最大是多少。

考虑dp,设 \(dp_{u,0}\) 表示考虑完以 \(u\) 为根的子树,其中 \(u\) 到它父亲的边不必被删去能获得的最大权值; \(dp_{u,1}\) 表示考虑完以 \(u\) 为根的子树,其中 \(u\) 到它父亲的边必须被删去能获得的最大权值,设 \(w_u\) 表示 \(u\) 和他父亲连边的边权,转移就比较显然了:

\[dp_{u,0}=\sum_{v\ is\ u's\ son}\max(dp_{v,0},dp_{v,1}+w_v) \]

\[dp_{u,1}=dp_{u,0}-\min_{v\ is\ u's\ son}(\max(dp_{v,0},dp_{v,1}+w_v)-(dp_{v,0}+w_v)) \]

方便起见,再设一个 \(dp_{u,2}=\max(dp_{u,0},dp_{u,1}+w_{u})\) ,那么转移:

\[dp_{u,0}=\sum_{v\ is\ u's\ son}dp_{v,2} \]

\[dp_{u,1}=dp_{u,0}-\min_{v\ is\ u's\ son}(dp_{v,2}-(dp_{v,0}+w_v)) \]

\[dp_{u,2}=\max(dp_{u,0},dp_{u,1}+w_u) \]

最后答案就是 \(dp_{root,0}\)

这是在根确定的时候我们得到的转移方程,接下来的问题就是换根时如何改变dp值了。

假设当前根是 \(u\) ,然后根要从 \(u\) 换为 \(v\) (其中 \(v\)\(u\) 的儿子)首先改变 \(w\) ,然后更新dp值: \(dp_{u,0}\) 直接减去 \(dp_{v,2}\) 即可,对于处理 \(dp_{u,1}\) 时需要的取 \(\min\) 操作,我们可以记录一个最小值和一个次大值,如果 \(dp_{v,2}-(dp_{v,0}+w_v)\) 是最小值,那么更新 \(dp_{u,1}\) 是就用次小值更新,否则就用最小值,然后更新 \(dp_{u,2}\) ,接着用 \(dp_{u,2}-(dp_{u,0}+w_u)\) 来更新 \(v\) 的最小次小值,最后更新 \(v\) 的dp值即可实现换根。

还有要注意的是,换完根后要换回来。

求出以每个点作为根时的dp值,那么最终答案就是每个点作为根时答案的最大值。

「NOIP模拟赛」小奇的仓库

用来学习换根dp的一道题。

先考虑确定根时如何做。

\(sz_{i,j}\) 表示以 \(i\) 为根的子树中到 \(i\) 距离在模 \(16\) 意义下为 \(j\) 的点的数量, \(sm_i\) 表示以 \(i\) 为根的子树中到 \(i\) 的距离和,那么某个根的答案就是 \(sm_{root}+\sum_{i=0}^{15}sz_{root,i}\times((i\oplus m)-i)\)

考虑换根,发现直接做就行了,因为只有加减。。。

最后要注意的就是:题目中问的是 \(i\)其它所有星球的花费时间总和,所以要记得减掉 \(m\)

Fox And Travelling

先拓扑排序求出所有可以被遍历到的点,如果有环就不行,所以最后可以被遍历到的点一定组成了一座森林,对于森林中的某棵树,如果它挂在不可被遍历到的点上,就把它视为有根树,根为和不可遍历到的点相连的那个点,否则就把它视为无根树。

对于一棵有根树,我们设 \(dp_{i,j}\) 表示以 \(i\) 为根的子树中遍历 \(j\) 个点的方案数,考虑将 \(v\) 并入 \(u\)

\[dp_{u,x+y}\gets dp_{u,x+y}+dp_{u,x}\times dp_{v,y}\times C_{x+y}^y \]

特殊的,一开始的 \(sz_u\) 设为 \(0\)\(dp_{u,0}\) 设为 \(1\) ,最后再将 \(sz_u\) 加一,同时 \(dp_{u,sz_u}=dp_{u,sz_u-1}\) ,因为如果选了 \(sz_u\) 个点,相当于是将整棵子树遍历,此时要考虑到点 \(u\) 本身。

对于一棵无根树,我们可以枚举它的根,对于一个遍历到的点的数量为 \(s\) 的方案数,除非 \(s=sz_{root}\) ,我们发现它恰好被多算了 \(sz_{root}-s\) 次,直接除回去就行了。

最后的答案就是把森林里每棵子树地答案做一遍背包合并即可。


2020-5-27

Stranger Trees

矩阵树定理。

矩阵树定理求的是这个:

\[\sum_T\prod_{e\in T}w_e \]

对于某条边,如果它属于原图,那么设这条边的边权是 \(x\) ,否则设这条边边权为 \(1\) ,那么求出来的就是一个多项式,然后 \(x^o\) 的系数就是 \(k=o\) 时的答案。

显然不好直接求,带入 \(n\) 个值后高斯消元出最后的多项式。

[JSOI2018]潜入行动

树形背包,显然没有黑题难度,估计是恶评。

\(dp_{i,j,0/1,0/1}\) 表示处理完了以 \(i\) 为根的子树,里面使用了 \(j\) 个监听设备,其中第 \(i\) 号节点是否存在监听设备,是否被监听设备覆盖的方案数,考虑将子树 \(v\) 并入 \(u\)

\[dp_{u,x+y,0,0}\gets dp_{u,x,0,0}\times dp_{v,y,0,1} \]

\[dp_{u,x+y,0,1}\gets dp_{u,x,0,1}\times dp_{v,y,0/1,1}+dp_{u,x,0,0}\times dp_{v,y,1,1} \]

\[dp_{u,x+y,1,0}\gets dp_{u,x,1,0}\times dp_{v,y,0,0/1} \]

\[dp_{u,x+y,1,1}\gets dp_{u,x,1,1}\times dp_{v,y,0/1,0/1}+dp_{u,x,1,0}\times dp_{v,y,1,0/1} \]

时间复杂度: \(\mathcal O(nk)\)

[POI2014]HOT-Hotels其加强版

\(f_{i,j}\) 表示在 \(i\) 的子树内,离 \(i\) 距离为 \(j\) 的点数,设 \(g_{i,j}\) 表示在 \(i\) 的子树内,满足 \(\operatorname{dist}(x,i)=\operatorname{dist}(y,i)\) 并且 \(\operatorname{dist}(\operatorname{lca}(x,y),i)+j=\operatorname{dist}(\operatorname{lca}(x,y),x)\) 的点对 \((x,y)\) 的数量。

考虑一棵子树一棵子树地合并,将 \(v\) 并入 \(u\)

\[ans\gets ans+f_{u,x}\times g_{v,x+1}+f_{v,x}\times g_{u,x+1} \]

\[g_{u,x+1}\gets g_{u,x+1}+g_{v,x+2}+f_{u,x+1}\times f_{v,x} \]

\[f_{u,x+1}\gets f_{u,x+1}+f_{v,x} \]

考虑到状态第二维和深度有关,直接长链剖分优化即可,注意 \(g\) 是反着来的,空间建议开大一点。

Dominant Indices

用来学习长链剖分优化dp的一道题。

状态都设好了,直接转移:

\[d(u,x)=\begin{cases}1 &\ (x=0)\\\sum_{v}d(v,x-1) &\ (x\ne 0)\end{cases} \]

长链剖分优化即可。

Lomsat gelral

用来学习 \(\rm dsu\ on\ tree\) 的一道题,相当于是模板,就不说了。

Don't fear, DravDe is kind

一道假的黑题,难度大概蓝?

显然卡车 \(u\) 和卡车 \(v\) 可以放到一起必须要满足 \(c_u+l_u+r_u=c_v+l_v+r_v\) ,可以开一个桶,里面存储这所有可以放大一起的卡车,然后一个桶一个桶地考虑,可以把卡车 \(u\) 抽象为一个区间 \([l_u+1,l_ u+c_u]\) ,然后题目便转化为给定若干个区间,选出一些区间使得其恰好填满整个位置,最大化权值和,直接dp就行了,然后要记录转移。

一种复杂度可能不怎么优的做法:

卡车 \(v\) 可以接在卡车 \(u\) 后面当且仅当 \(l_u+c_u=l_v\) 并且 \(r_u=r_v+c_v\) ,直接用一个二维的 \(map\)\(q_{x,y}\) 记录当 \(l+c=x,r=y\) 时能达到的最大权值和,在转移的时候顺便记录一下就行了。


2020-5-25

选举预测

神仙题.jpg

如果 \(u\) 赢过 \(v\) ,那么我们就连一条从 \(u\)\(v\) 的有向边,那么就会形成一张有向图。

首先,在同一个点双连通分量里面,任何点都可以打败其他所有点,所以貌似可以缩点?但是对于没有任何关系的点咋办?我们可以让它们间有关系!

如果点 \(u\) 和点 \(v\) 没有连边,我们就在它们之间连一条双向边(即 \(u\)\(v\) 连一条, \(v\)\(u\) 连一条),表示 \(u\) 可以打败 \(v\)\(v\) 可以打败 \(u\) ,操作后还是满足在同一个点双连通分量里面任何点都可以打败其他所有点。

然后再缩点,缩完点后就是一张有向无环图,找到入度为 \(0\) 的点就是答案。

复杂度 \(n^2\) ,显然过不了,考虑缩完点后的图有什么性质。

由于缩完点后任何点之间都有连边,所以只会出现恰好一个入度为 \(0\) 的点!考虑在不连完所有边的情况下(即在原图下)找到答案。

可以先找到一个必胜的点,那么这个点最终一定被缩成了最后那个入度为 \(0\) 的点,然后从该点开始 \(\rm bfs\) ,设该点为 \(u\) ,如果原图中不存在一条 \(u\)\(v\) 的边,那么处理完后的图必然存在一条 \(v\)\(u\) 的边,那么 \(u\)\(v\) 必然缩成了一个点,否则缩完点后 \(u\) 所在的点的入度就不是 \(0\) ,于是我们就把点 \(v\) 加入队列继续 \(\rm bfs\)

然而,复杂度还是 \(n^2\) ,因为我们 \(\rm bfs\) 是扫到的边集是题目中给出的 \(m\) 条边的补集,它是 \(n^2\) 级别的!

可以用链表优化,这样原本已经在队列里的点就不会再次被扫到,复杂度降为 \(\mathcal O(n+m)\)

完结撒花。


2020-5-23

[APIO2016]烟火表演

好的,这辈子题解都不可能只有一句话了。

\(dp_{i,j}\) 表示以 \(i\) 号节点为根的子树到 \(i\) 的父亲的距离全部修改为 \(j\) 所需要的最小花费。

转移:

\[dp_{u,s}=\min_{k=0}^s(\mid val_u-k\mid+\sum_{v\ is\ u'son}dp_{v,s-k}) \]

\(g_{u,k}=\sum_{v\ is\ u'son}dp_{v,k}\) ,那么:

\[dp_{u,s}=\min_{k=0}^s(\mid val_u-k\mid +g_{u,s-k}) \]

显然直接扫复杂度太劣了,如何优化?把 \(dp_{u,s}\) 看做是一个自变量为 \(s\) 的函数,观察这个函数的性质。

首先,叶子结点的函数图像一定是斜率为 \(-1\) 的一条折线加上斜率为 \(1\) 的一条折线。

然后从叶子节点手推一下,可以得到以下几个性质:

  1. \(dp_u\)\(g_u\) 为下凸函数。
  2. \(g_u\) 可以直接推得 \(dp_u\)
  3. \(dp_u\)\(g_u\) 函数下降段斜率最大为 \(-1\) ,上升段斜率最小为 \(1\)

假设函数 \(g_u\)\([L,R]\) 段取值为最小值,由 \(g_u\) 推得 \(dp_u\) 的方法如下:

  1. 将函数在 \([1,L]\) 的折线往上平移 \(val_u\) 个单位。
  2. 将函数在 \([L,R]\) 的折线往右平移 \(val_u\) 个单位。
  3. 将函数在 \([R,+\infty]\) 的折线往右平移 \(val_u\) 个单位并把斜率改为 \(-1\)

这时空出了一段斜率为 \(-1\) 的折线,直接连上即可。

还有个性质: \(g_u\) 最右段的斜率是 \(u\) 的儿子数。

但是还有个问题:如何表示这个函数?

我感觉这题最妙的地方就是这里:用转折点的横坐标表示!

我们规定从左往右每经过一个转折点斜率就加 \(1\) ,那么:

  1. 函数相加就是转折点的并(可以在纸上推一下)。
  2. \(g_u\) 转到 \(dp_u\) 相当于是先把横坐标最大的儿子数个的转折点弹出,然后把平行段的 \([L,R]\) 取出,插入 \([L+val_u,R+val_u]\) ,即再弹出两个横坐标最大的两个转折点,把它们加上 \(val_u\) 后再插回去。

那么要实现:

  1. 合并两个点集。
  2. 弹出权值最大的点。
  3. 插入点。

于是,便自然而然地想到可并堆。

完结撒花!


2020-5-22

Steps to One

好的,莫比乌斯反演+期望dp。

另一种做法(非dp):

设答案是 \(E(x)\) ,最终长度大于等于 \(k\) 的概率为 \(P(k)\),那么:

\[E(x)=\sum_{i=1}^{+\infty}P(i) \]

考虑枚举前 \(i-1\) 个数的 \(\gcd\)

\[\to=1+\sum_{i=2}^{+\infty}\frac{-\sum_{j=2}^{m}\mu(j)(\lfloor\frac{m}{j}\rfloor)^{i-1}}{m^{i-1}} \]

\[\to=1-\sum_{j=2}^{m}\mu(j)\sum_{i=1}^{+\infty}\frac{(\lfloor\frac{m}{j}\rfloor)^{i}}{m^i} \]

\[\to=1-\sum_{j=2}^m\mu(j)\frac{\lfloor\frac{m}{j}\rfloor}{m}\lim_{n\to +\infty}\dfrac{1-(\frac{\lfloor\frac{m}{j}\rfloor}{m})^n}{1-\frac{\lfloor\frac{m}{j}\rfloor}{m}} \]

\[\to=1-\sum_{j=2}^m\mu(j)\dfrac{\lfloor\frac{m}{j}\rfloor}{m-\lfloor\frac{m}{j}\rfloor} \]

时间复杂度 \({\mathcal O(m)}\)

Little Sub and Piggybank

贪心+dp。

\(dp_{i,j}\) 表示这次在第 \(i\) 天买了物品,上次买物品是第 \(j\) 天的最大获利。

贪心地想,要让买第 \(i\) 个物品的门槛尽量低,要让买下一个物品的能够达到的水平尽量高,我们当然希望在 \(j+1\sim i\) 天内,投币数量为 \(\frac{w_i}{i-j}\)

于是得到转移:

\[dp_{i,j}=w_i+\max_{k=0}^{j-1}dp_{j,k}\ \ \ (\frac{w_i}{i-j}\le \frac{w_j}{j-k}) \]

优化一下,设 \(dp_{i,j}\) 表示这次在第 \(i\) 天买了物品,上次买物品是 \(j\sim i-1\) 天的最大获利。

转移:

\[dp_{i,j}=\max(dp_{i,j+1},w_i+dp_{j,\lceil j-\frac{w_j}{w_i}(i-j)\rceil}) \]

答案:

\[\max_{i=1}^ndp_{i,0} \]

Flipping Game

计数dp。

\(dp_{i,j}\) 表示当前行有 \(i\) 盏灯需要改变,还要操作 \(j\) 轮最后达成要求的方案数。

转移就很显然了:

\[dp_{i,j}=\sum_{l=\max(0,m+i-n)}^{\min(i,m)}{i\choose l}{n-i\choose m-l}dp_{i+m-2l,j-1} \]

初始化:

\[dp_{0,0}=1 \]

[AGC030D] Inversion Sum

神仙题。

居然有人把概率dp出成了计数dp。

直接计数不好做,考虑转概率dp。

\(dp_{i,j}\) 表示在经过了当前若干操作后 \(a_i>a_j\) 的概率。

假如出现了交换 \(u,v\) 的操作,相当于是以 \(50\%\) 的概率执行,所以转移:

\[dp_{v,u}=dp_{u,v}=\frac{dp_{u,v}+dp_{v,u}}{2} \]

\[dp_{i,u}=dp_{i,v}=\frac{dp_{i,u}+dp_{i,v}}{2} \]

\[dp_{u,i}=dp_{v,i}=\frac{dp_{u,i}+dp_{v,i}}{2} \]

最后答案就是:

\[2^q\sum_{i=1}^n\sum_{j=i+1}^ndp_{i,j} \]


2020-5-20

Misunderstood … Missing

未来费用的一道好题。

先放上翻译:

打怪,有 \(n\) 轮,一开始用两个参数 \(A\)\(D\) ,初始值都是0,每轮开始时执行操作 \(A=A+D\) ,然后第 \(i\) 轮有以下几种操作选择:

  1. 造成伤害 \(A+a_i\)
  2. \(D=D+b_i\)
  3. \(A=A+c_i\)

最大化造成伤害之和。

前面的 \(2\)\(3\) 操作会影响后面的操作 \(1\) ,考虑反着dp,设 \(dp_{i}\) 表示处理完了 \(i+1\sim n\) 的操作能造成的最大伤害,但是我们并不知道选择操作 \(2\)\(3\) 会造成多少伤害,所以还要记录一些东西。

假设在 \(i+1\sim n\) 这些操作中选了 \(j\) 个操作 \(1\) ,这些操作中选的操作 \(1\) 所在的操作位置之和为 \(k\) (即 \(k=\sum_{l=1}^jpos_l\) ),那么操作 \(2\) 造成的伤害就是 \((k-i\times j)\times b_i\) ,操作 \(3\) 造成的伤害就是 \(j\times c_i\)

转移如下:

\[dp_{i-1,j+1,k+i}\gets \max(dp_{i-1,j+1,k+i},dp_{i,j,k}+a_i) \]

\[dp_{i-1,j,k}\gets \max(dp_{i-1,j,k},dp_{i,j,k}+b_i\times (k-i\times j)) \]

\[dp_{i-1,j,k}\gets \max(dp_{i-1,j,k},dp_{i,j,k}+c_i\times j) \]

Magic Gems

矩阵快速幂加速dp。

这题一开始想复杂了,上来直接推组合数,得出答案:

\[\sum_{i=0}C_{n-i(m-1)}^i \]

然后就不会写了。。。

看完题解后才发现自己完全想复杂了,直接dp,设 \(dp_i\) 表示分解成 \(i\) 颗宝石的方案数,转移:

\[dp_i=dp_{i-1}+dp_{i-m} \]

记录后 \(m\) 位,矩阵快速幂就行了。

所以说题目要更难的话建议直接给这个式子:

\[\text{求}\sum_{i=0}C_{n-i(m-1)}^i \]

那估计要推蛮久。

Comparing Your Heroes

状压dp。

\(vis_{s}\) 表示在选出点集 \(s\) 后接下来能选的点集, \(dp_{s}\) 表示选出点集 \(s\) 的方案数。

转移:

\[dp_{s\cup i}\gets dp_{s\cup i}+dp_s \ \ \ (i\in vis_s) \]

Makoto and a Blackboard

先将 \(n\) 分解质因数,假设 \(n=\prod_{i=1}^mp_i^{h_i}\)

将每一个质因数分开考虑。设 \(dp_{w,i,j}\) 表示经过 \(w\) 次操作(每次操作把 \(i\) 随机变成 \([0,i]\) 中的一个数)后 \(i\) 变成 \(j\) 的概率 ,那么答案是:

\[\prod_{i=1}^m\sum_{j=0}^{h_i}dp_{k,h_i,j}\times p_i^j \]

转移:

\[dp_{w,i,j}=\frac{\sum_{l=0}^idp_{w-1,l,j}}{i+1}=\frac{i\cdot dp_{w,i-1,j}+dp_{w-1,i,j}}{i+1} \]

初始化:

\[dp_{0,i,j}=[i==j] \]

Jongmah

贪心+dp。

显然, \(\{1,2,3\}\times 3\)\(\{1,1,1\},\{2,2,2\},\{3,3,3\}\) 没有任何区别,所以相邻的三个组成一对可以认为最多只会组两次。

\(dp_{i,j,k}\) 表示考虑完了前 \(i\) 种麻将,其中组成了 \(j\)\(\{i-1,i,i+1\}\) ,组成了 \(k\)\(\{i,i+1,i+2\}\)

\(sum_i\) 表示第 \(i\) 种麻将的数量,转移:

\[dp_{i,j,k}=\max_{l=0}^{3\operatorname{and}l+j+k\le sum_i}(dp_{i-1,l,j}+\lfloor\frac{sum_{i}-l-j-k}{3}\rfloor) \]

初始化:

\[dp_{i,j,k}=\begin{cases}0&\ (i=0\operatorname{and}j=0\operatorname{and}k=0)\\ -\inf&\ (i\ne 0\operatorname{or}j\ne 0\operatorname{or}k\ne 0)\end{cases} \]

答案:

\[dp_{m,0,0} \]

[NOIP2018模拟赛] 小P的技能

蛮妙的一道题,没有独立想出来。

题意就是询问 \(n\) 个点的二叉树深度大于等于 \(k\) 的方案数。

\(dp_{i,j}\) 表示 \(i\) 个点的二叉树深度小于等于 \(j\) 的方案数。

转移:

\[dp_{i,j}=\sum_{k=0}^{i-1}dp_{k,j-1}\cdot dp_{i-k-1,j-1} \]

初始化:

\[dp_{0,x}=1 \]

答案:

\[dp_{n,n}-dp_{n,k-1} \]

Array Without Local Maximums

相邻三个数相邻大小关系唯一不合法的情况就是:

\[a_{i-1}<a_{i}>a_{i+1} \]

\(dp_{i,j,sta}\) 表示填完前 \(i\) 个数组,最后一个数字为 \(j\) ,状态为 \(sta\) 的所有方案,其中当 \(sta=0\) 时, \(a_{i-1}>a_i\) ,当 \(sta=1\) 时, \(a_{i-1}=a_i\) ,当 \(sta=2\) 时, \(a_{i-1}<a_i\)

转移:

\[dp_{i,j,0}=\sum_{k>j}dp_{i-1,k,0/1}=dp_{i-1,j+1,0/1}+dp_{i,j+1,0} \]

\[dp_{i,j,1}=dp_{i-1,j,0/1/2} \]

\[dp_{i,j,2}=\sum_{k<j}dp_{i-1,k,0/1/2}=dp_{i-1,j-1,0/1/2}+dp_{i,j-1,2} \]

初始化:

\[dp_{0,0,1}=1 \]

最后答案是:

\[\sum_kdp_{n,k,0/1} \]

Tree with Maximum Cost

有点厚颜无耻地说着这题是换根dp。

树形dp/换根dp。

考虑换根的影响,如果根从 \(fa_u\)\(u\) ,改变值为 \(sz_{root}-2sz_u\) ,直接 \(O(n)\) 求出 \(sz\) 然后再 \(O(n)\) 计算答案就行了。

[ABC118D] Match Matching

数位dp/背包dp。

\(dp_{i,j}\) 表示能否用 \(j\) 根火柴棒拼出 \(i\) 位,设 \(us_k\) 表示第 \(k\) 个数字需要的火柴棒数量,转移:

\[dp_{i,j}=\operatorname{or}_{k=1}^mdp_{i-1,j-us_k} \]

然后贪心,先选位数尽量大,再选高位尽量大,判是否可行就行了。

注意细节,不要让数组越界。

Flood Fill

区间dp,先把相邻相同颜色合并,记 \(dp_{l,r}\) 表示将 \([l,r]\) 涂成相同颜色的最小步数,转移:

\[dp_{l,r}=\begin{cases}dp_{l+1,r-1}+1&\ (a_l=a_r)\\\min(dp_{l,r-1},dp_{l+1,r})+1 &\ (a_l\ne a_r)\end{cases} \]

Colorful Bricks

相同颜色归为一起,第一种颜色有 \(m\) 种选法,其他颜色有 \(m-1\) 种选法,然后再乘以把 \(n-(k+1)\) 个相同的球丢到 \(k+1\) 个盒子里去(允许盒子为空)的方案数。

答案为:

\[m(m-1)^kC_{n-1}^k \]

Pie Rules

\(dp_{i}\) 表示先手从 \(i\) 取到 \(n\) 可以获得的最大利益,设 \(sum_i\)\(\sum_{j=i}^na_i\) ,转移如下:

\[dp_{i}=\max(dp_{i+1},sum_{i}-dp_{i+1}) \]


博弈论

把之前博弈论的题目也放进来吧,反正也算是题解,不过 \(\rm AC\) 时间倒是忘了。

洛谷P3185 [HNOI2007]分裂游戏

把第\(i\)个瓶子了的豆子看作是数量为\(n-i-1\)的一堆石子,那么每次操作相当于是将一堆石子变成数量比它少的两堆石子,由于\(2\le n\le 21\)很小,直接算出数量为\(1\dots n-1\)的石子的\(SG\)函数值,用\(SG\)定理,看异或起来是不是\(0\)就行了。

输出方案直接枚举选哪三个,判一下选完后的\(SG\)函数值是否合法就行了。

洛谷P5675 [GZOI2017]取石子游戏

博弈论加计数,考虑动规,记\(dp_{i,j}\)表示选出的石子堆包含编号为\(i\)的石子且石子数量异或起来为\(j\)的方案数,若编号为\(i\)的石子堆数量为\(a_i\),那么答案便是\(\sum_{i=1}^{n}(dp_{i,0}+\sum_{j=a_i+1}dp_{i,j})\),记值域最大为\(x\),时间复杂度\(O(n^2x)\)

洛谷P3480 [POI2009]KAM-Pebbles

相当于是对相邻两堆石子的差做阶梯NIM游戏。

poj1740 A New Stone Game

用手玩和打表等方法可以猜出以下结论(其实我也没有好方法找结论的):

\(n\)为偶数且恰好可以分成\(n/2\)份使得每份的两堆数量相等,先手必败;否则先手必胜。

证明:

\(n\)为奇数,排序后可以保证\(a_n>(a_{n-1}-a_{n-2})+(a_{n-3}-a_{n-4})+\dots+(a_2-a_1)\),直接把\(a_{n-2k}\)变成\(a_{n-2k+1}\),剩下的丢掉就可以变成必败态了。

\(n\)为偶数,排序好可以保证\(a_n>(a_{n-1}-a_{n-2})+(a_{n-3}-a_{n-4})+\dots+(a_3-a_2)+a_1\),直接把\(a_{n-2k}\)变成\(a_{n-2k+1}\),剩下的拿到\(a_1\)就变成必败态了。

必败态无论如何都不可能变成必败态。

\(n=0\)时,也满足必败态的要求。

所以原结论成立。

洛谷P2599 [ZJOI2009]取石子游戏

此神仙题不可做(确信

\(L_{l,r}\)表示如果在\(l\)\(r\)这个区间左边添上一堆石子数量为\(L_{l,r}\)的石子堆时先手必败,记\(R_{l,r}\)表示如果在\(l\)\(r\)这个区间右边添上一堆石子数量为\(R_{l,r}\)的石子堆是先手必败。

首先证明\(L_{l,r}\)\(R_{l,r}\)唯一,假设\(L_{l,r}\)存在两个取值\(x,y(x<y)\),那么当添上去的石子堆数为\(y\)时先手可以把\(y\)拿成\(x\),换成后手拿,此时后手必败,先手必胜,与假设矛盾(当添上去石子数为\(y\)时先手必败),所以\(L_{l,r}\)唯一,\(R_{l,r}\)同理。

接下来证明\(L_{l,r}\)\(R_{l,r}\)存在,假设\(L_{l,r}\)不存在,即无论在左边添上去的石子数量为多少,先手都必胜,假设左边添上\(x\),那么先手必然不会拿左边的这个\(x\),因为拿了后还是必胜态,所以先手会从右边拿,那么在拿完后无论\(x\)为多少都是必败态,后手如果拿了左边的\(x\)得到的还是必败态,与“无论\(x\)为多少都是必败态矛盾”,所以\(L_{l,r}\)存在,\(R_{l,r}\)同理。

再证明一些结论吧:

引理一:

\(L_{l,r}=0\),那么\(R_{l,r}=0\)\(R_{l,r}=0\)时同理)。因为\(L_{l,r}=0\),局面为\((0,[l,r])\)\(([l,r])\)时先手必败。假设\(R_{l,r}\ne 0\),那么先手可以直接把右边拿成\(0\),此时局面变成\(([l,r])\),后手操作,所以后手必败,与原先假设先手必败矛盾,所以结论成立。

考虑\(L_{l,r}\)如何转移(\(R_{l,r}\)同理):

方便起见,记\(L=L_{l,r-1},R=R_{l,r-1},x=a_r\)

\[\mathsf{Case 1: x=R} \]

\(L_{l,r}=0\)。相当于原本就是必败态。

\[\mathsf{Case 2: x<L,x<R} \]

\(L_{l,r}=x\)。由必胜必败态的定义可以知道当石子数量为\((0\sim L-1,[l,r-1])\)或者\(([l,r-1],0\sim R-1)\)时先手必胜。可以在左边添上一堆数量为\(x\)的石子,此时先手从哪一边拿石子,后手就从另一边拿相同数量的石子,此时必然会有一堆先被拿完,拿完后操作方变成后手,局面变为\((0\sim L-1,[l,r-1])\)\(([l,r-1],0\sim R-1)\),后手必胜。

\[\mathsf{Case 3: R<x\le L} \]

\(L_{l,r}=x-1\)。假设先手拿左边,左边剩\(y\)个石子:若\(y<R\),后手可以直接把右边拿成\(y\),变成\(\mathsf{Case 2}\)里面的情况;若\(y\ge R\),后手把右边拿成\(y+1\),回到\(\mathsf{Case 3}\)。假设先手拿右边,右边剩\(y\)个石子:若\(y=R\),如果\(R\ne 0\),左边剩余石子数必然大于\(0\),后手直接把左边拿完,变成\(\mathsf{Case 1}\),否则\(R=0\),由引理一得到\(L=0\),不存在\(R<x\le L\),即该情况不存在;若\(y<R\),那么先手上一步至少拿了两个石子(\(y\ge R+1\to y\le R-1\)),左边石子数量必然大于\(y\),后手可以把左边拿成\(y\),变成\(\mathsf{Case 2}\);若\(y>R\),后手把左边拿成\(y-1\),回到\(\mathsf{Case 3}\)

\[\mathsf{Case 4: L\le x<R} \]

\(L_{l,r}=x+1\)。这个和\(\mathsf{Case 3}\)类似,建议读者先自己想想。假设先手拿左边,左边剩\(y\)个石子:若\(y=L\),如果\(L\ne 0\),右边剩余石子数必然大于\(0\),后手直接把右边拿完,变成\(\mathsf{Case 1}\),否则\(L=0\),由引理一得到\(R=0\),不存在\(L\le x<R\),即该情况不存在;若\(y<L\),那么先手上一步至少拿了两个石子(\(y\ge L+1\to y\le L-1\)),右边石子数量必然大于\(y\),后手可以把右边拿成\(y\),变成\(\mathsf{Case 2}\);若\(y>L\),后手把右边拿成\(y-1\),回到\(\mathsf{Case 4}\)。假设先手拿右边,右边剩\(y\)个石子:若\(y<L\),后手可以直接把左边拿成\(y\),变成\(\mathsf{Case 2}\);若\(y\ge L\),后手把左边拿成\(y+1\),回到\(\mathsf{Case 4}\)

\[\mathsf{Case 5: x>L,x>R} \]

\(L_{l,r}=x\)。分类讨论后不难变成以上四种\(\mathsf{Case}\),请读者自行思考。

\(R_{l,r}\)\(L_{l,r}\)的求解类似,不再赘述。

最后只要判断一下\(L_{2,n}\)是否等于\(a_1\)就可以判断胜负了。

posted @ 2021-04-08 22:18  xiaolilsq  阅读(348)  评论(3编辑  收藏  举报