record 1.8-1.12

CF1919 D

这个东西我们发现可以写成 \(\{0\}\in S,\forall s,t\in S,combine(s+1,t)\in S,combine(s,t+1)\in S\)

你发现这个东西很厉害啊,但是一点用都没有。我们直接照这个做是 \(O(n^3)\) 的。

然后是 sol。

你发现我们 n^3 的做法是每次考虑从上往下把左右子树拆开,然后分治下去。那我们可以试着反过来考虑,每次合并两个儿子。这个想法其实是自然的,因为它给的树的性质是一定有 0/2 个儿子。

你发现合并两个儿子的要求是两个相邻值差为 1。但是,有很多符合条件的,我们应该合并谁?你考虑全局最大值,它只能和它减 1 合并,所以留着它没有一点用,我们可以优先合并这些。

我们实现这个过程即可。

CF1919 E

赛时在想 dp,这个有一个大概是 \(n^5\) 的做法,但是没啥前途,所以不会啊啊啊啊啊啊。

下面的内容都是在瞄了一眼 sol 之后写的。

我们记排序后的是 \(p\),排序前的是 \(q\),那很显然 \(q,a\) 是一一对应的,所以我们对 \(q\) 计数即可。

我们现在不妨假装知道了 \(q_n\),这样带来的好处就是我们知道 \(a\) 里面分别有多少个 \(\pm 1\)

经过一些观察之后,我们发现,任何情况都可以由 \([+1,+1,\dots,+1,-1,-1,\dots,-1]\) 通过中间插入 \([+1,-1]\) 来达到。其中,前面那个东西有 \(p_n\)\(+1\)\(p_n-q_n\)\(-1\)

我们来证明一下。考虑倒过来,我们证明任意一种都可以通过消除相邻的两个 \([+1,-1]\) 最终缩到初始情况。那你考虑消消消最后一定是前面一坨 \(+1\) 后面一坨 \(-1\),然后先证明前面 \(+1\) 正好加到最大值。这个你可以考虑第一个最大值位置,当且仅当前面出现一个 \(-1\) 会消,那它就不是最大值了。你考虑证明 \(-1\) 之后正好到 \(q_n\),这个你发现你的消除操作不会改变 \(q_n\) 即可。

好的,我们说明了这个很有趣的结论。接下来的问题是,我们这样操作的方案,跟 \(a\) 的方案是不是一一对应的。很显然不是,你考虑比方说左右两段每个位置上各操作一次,两个不同操作顺序显然会对应相同的结果。但是有的时候,操作顺序又是必须的。你比方说,左边一段先操作一下之后,在下沉下去的地方,再操作一次,这个就是有顺序要求的。

所以,我们尝试定一个顺序,然后让它们的方案一一对应。那一个直观的想法是,下面的东西可能会由操作一次“下沉”的地方而产生,所以我们要先把“下沉”给生成出来。那我们只要按照值从大到小操作就可以了。

那我们现在要对规定了顺序的操作方案计数。一次操作,会使得自己这个位置和自己减一的位置都加一。你发现我们刚刚规定的顺序,是非常方便计数的。我们每次下沉生成出需要的个数,然后算一个组合数就可以了。

总复杂度 \(O(n^2)\),还有一个类似的题,但是是 \(O(n\log n)\) 的,待会看看。

CF1919 F2

看了一些 hint。

我们最大流建模,转成最小割。那你不妨假设你知道了哪些位置的 \(c\) 被割掉了,然后接下来对每个连通块怎么算。我们发现肯定是保留一个 \(b\) 的前缀和一个 \(a\) 的后缀,不然就可以通过 \(c\) 流过来了。我们可以先假设割的都是 \(a\),然后计算 \(b-a\) 的前缀和,取最小值,即可得到这个连通块的最优解。同时注意到,连通块里的 \(c\) 有 0 完全没问题,因为这样并不优,外层决策一定会考虑到。

那你接下来考虑怎么决策 \(c\) 割掉的位置。\(dp_i=\min(dp_j+val(j,i))\) 即可。你发现这个东西没一点用。

我们注意不到,这个信息是可以合并的。具体来说,如果没有区间跨过中点,我们可以直接合并两个子区间;如果有跨过中点的,我们考虑这个区间的前缀和选取的断点在哪里,分左右两边讨论,你发现都可以写成只跟一边有关的形式,拆过去,算最小合并就行了。

看了 sol。sol 里是先考虑怎么割 \(a,b\),然后再根据它的情况去割 \(c\),这个做法跟我应该是本质相同的,不过它好像更简洁一些。而且,它的前面证明每个点的 \(a,b\) 只有一个会被割应该是多余的,我们大不了分三种情况而不是两种情况就行了。

我们还是写 sol 的做法吧。

不过,我想证一下。我们只证不会同时割两个。

你考虑一个 \(p\),它的两个边都被割了。你考虑割完之后,还有没有 \(s\to p,p\to t\) 的路径。显然两者不会同时存在,我们不妨假设只有 \(s\to p\) 的路径。那我们可以把 \(a_p\) 给留下来。反之亦然。

呃呃这个好没意思啊。

zroi#4 B

场上在干别的事情,一点都没想。

我们首先发现 \(n^4\) 已经爆了,这说明我们需要通过某些方式快速计算出有一个自由度的情况。

你比方说我们现在知道 \(l_1,r_1,l_2\),在等 \(r_2\)。考虑一个有解的充要条件,首先每一行到了 \(r_1\) 时每个段长度都必须是偶数。其次,在这个过程中,不能有我现在是 1 但是下一个位置突然是 0 的情况,这样的话这一整行都不能要。然后,\([l_2,r_2]\) 内每一列的 1 段长度都得是偶数。

我们上面这些东西,好像在说能覆盖的充要条件,是每一行、每一列的每个 1 段长度都是偶数。我们来证明一下充分性。

我们考虑使用数学归纳法,对行的长度进行归纳。你先考虑 \(n=2\) 的时候,这个正确性比较显然。然后现在你考虑最后一行,你先覆盖一下,由于这一行 1 段长度是偶数,所以这一行可以被覆盖好。由于每一列 1 段长度是偶数,所以下一个对应位置也是 1,这样我们说明了可以这样覆盖。那我们就归纳到了 \(n-1\) 的情况。

好的,那我们接下来就是要实现这个东西。正如最开始所说,我们枚举 \(l_1,r_1,l_2\) 去算有几个合法的 \(r_2\)。我们现在知道了 \([l_1,r_1]\) 这些里面,有哪些行是合法的,接下来我们要把合法的行拼到一起,判断列是否合法。列合法的条件是长度为偶数,我们可以考虑一个类似于 xor hash 的东西,你考虑记录每一列后缀上的情况,然后每次 xor 一下就行了。

呃呃,上面说的都是假的。你考虑这样一个情况:

0110
1111
1111
0110

这就假了。

我们进行 hash 的时候,不是基于 inp 数组,而是基于 tag 数组,就是基于我们当前这一列是还差一个还是正好可以的这个情况来 hash 就行了。

ARC146 E

给一个序列 \(a\),问你有多少种重排(重复算一种),满足相邻两项的差恰好为 1。

\(n\le 2\times10^5\)

这个就是上面说的类似的题。

呃呃,这个是不是用那个连续段 dp 的做法啊。我们想一下。

你比方说现在有 \(dp_{v,i,0/1,0/1}\) 表示考虑到 \(v\)\(i\) 个连续段,并且除了最左最右之外,每个段的两端都要是 \(v\),最左的右端点,最右的左端点也要是,但是最左的左端点,最右的右端点由两个 01 给出。

转移的时候,一次性考虑所有数被怎样使用。大概就是把必须放的先放下来,然后考虑那些自己新开段的东西怎么放。这个没怎么细想。

你仔细写一下,你发现有数的位置非常之少,我们记录一下即可。

看了 sol,跟上面说的基本一样。那上面那个题应该也可以这么做。

但是 sol 里的更新写的很好!首先我们发现 \(dp_{v,i,0,1}=dp_{v,i,1,0}\),其实我们可以直接设 \(dp_{v,i,k}\),其中 \(k\) 表示我们关心的位置有几个不是 \(v\)

然后考虑基于 \(dp_{v,i,k}\) 去更新别人。具体来说,我们往已经排好的 \(v+1\) 当中去插入 \(i\) 段,然后你去分讨有没有插到最外侧来决定要不要修改 \(k\)

gdkoi2024 D1T1

给一个 \(2n\) 个点的二分图,边权 01,构造一个异或和是 0 的完美匹配。

\(n\le 500\)

你先跑最大流,要求满流。然后如果现在这个匹配满足条件,那就不用管了。否则,我们要在残量网络上,找一个异或和是 1 的环。这个是不是做一个 floyd 就行了啊。

呃呃,看了 sol,应该是真的。

但是我比较闲,所以我们稍微来证明一下。

你考虑我们有残量网络 \(G\),最后的解是 \(G'\),你考虑一个类似于对称差的东西 \(T=G\oplus G'\),这个 \(T\) 每个点都满足流量平衡。那么我们可以在这个图上跑欧拉回路,这样我们就把它拆成了环。所以我们现在证明了这个东西可以被拆成若干个环。那么这些环里至少有一个异或和是 1,我们只要找一下就行了。

gdkoi2024 D1T2

给数组 \(a\),操作序列 \(op\),每个操作要么是区间赋值,要么是区间求和。

多次询问执行操作 \([l,r]\) 之后,所有求和操作的和。

\(n\le 5\times 10^5\)

我们先胡一个根号做法上去。你考虑对操作序列分块,每个块维护两个东西,第一个是区间求和的时候,求的和的数来自块内部的修改操作的和,第二个是求的和来自块外部给的初值每个位置被算了几次。这样我们成功从 \(O(qn\log n)\) 负优化到了 \(O(qn\sqrt{n})\)!实在是质的飞跃!

但是我们是不是可以考虑莫队。你考虑 \(r\) 的右移是非常简单的,\(l\) 的左移呢?加一个询问很简单,加一个修改,我们维护目前每个位置上有多少个数算的是初始值,也可以做。复杂度是 \(O(q\sqrt{n}\log n)\)。还是非常废物。

看了 sol 的复杂度,为啥单根号做 5e5 啊!!!让我想想。

是不是可以这样,我们发现每个整块的贡献其实是关于 \(l\) 的一个函数,那我们先想一下怎么处理出这个东西。你考虑对于一个块,我们先处理出每个位置加了来自块外部的多少次,把 \(l\) 左移的时候,你考虑自己区间内有多少个不是 0 的,然后把它们答案更新成自己这个数。这样每个数均摊被修改一次,所以这部分是单根号的。

考虑左右两个散块,左边那个散块很好做,因为一共只有 \(O(n)\),所以我们怎么预处理都可以。但是右边那个散块似乎没那么好做,两个端点在同一个块内的也没那么好做。

看了一点点 sol。

我们考虑把每次覆盖操作的值,设置成这一次的值减去上一次的。根据颜色段均摊,我们的总段数仍然是线性的。

现在,问题转化成了二维平面上你有一堆线段,然后每次问你一个矩形区域内的和。

不会啊!!!看了 sol。

我们先做一个简单版本:把区间赋值改成区间加。

这个你考虑分块,对于左边的散块,总数不多随便处理,对于散块对整块的贡献,散块会划分出 \(B\) 个区域,我们计算每个区域被计算了多少次就行了。对于整块内部,我们进行预处理,可以考虑值域分块进行平衡。事实上我们发现我们可以处理出来到每一个散点的答案。

对于两个端点都在散块内的,我们计算前缀修改对后缀询问的影响,每次后缀前移可以视为打差分标记,然后进行一次前缀和,枚举前缀修改,查询即可。

这个东西其实利用了一些询问在修改前,我们可以差分的性质。

然后回到原题,我们颜色段均摊先变成对相同区间进行修改。然后后面比较奇怪自己看 sol 吧。

某个题

给一张无向正权图,求分别删去每条边之后 \(1\to n\) 的最短路。

这个,我们先求一条最短路,然后考虑删掉这上面的边会发生什么。

我们不妨求出来最短路 DAG,然后考虑哪一条边是必须经过的,这个可以通过计数来解决。

对于这些必须经过的边,我们删掉之后,肯定是有影响的。

我们考虑删掉一条割边 \((u,v)\) 之后,\(1\to n\) 的最短路会长成什么样。你发现一定是有一个 \((x,y)\),使得走 \(1\to x\to y\to n\),其中 \(1\to x\) 在割边之前,\(y\to n\) 在割边之后,边 \((x,y)\) 跨过了割边。那现在我们会了一个枚举 \((x,y)\) 的做法,复杂度 \(O(nm)\),没啥用。

考虑优化一下,你大眼一扫,发现这个割边,应该可以排成一个序列,而 \((x,y)\) 能贡献到的位置,是一个区间。

我们来证明一下这个割边可以排成一个序列。考虑按照拓扑序来定义这个顺序,对于原 DAG 的任意一个拓扑序 \(id\),以及两条割边 \((u,v),(x,y)\)。因为 \((u,v)\) 会把图分成两部分,所以我们不妨假设 \((x,y)\) 在后面那个部分。显然有 \(id_u<id_v,id_x<id_y\),我们想证明 \(id_v\le id_x\),考虑反证法,不妨假设 \(id_v>id_x\),由拓扑排序的算法可以知道,如果我们把 \(id_x\) 之前的点都删完的话,那么 \(indeg_x=0\)。而此时 \(v\) 点并没有被删除,考虑 DAG 上任意一条 \(v\to x\) 的路径,这路径上有前一个点的 \(id\) 比后一个点大。所以就矛盾了。

那这样的话,我们只要按照拓扑序来排序,这个割边自然就成了一个序列。

接下来我们阐述另外一部分,我们声称这个区间是 \([id_x,id_y]\)。但我们要略微修改一下求拓扑序的方法。具体来说,我们先找到所有的割边,然后对于 \((u,v)\) 的起点 \(u\) 而言,我们把它的优先级放到最低。也就是说,把别的点都删完之后,我们再来删除这个。

算了,我们直接这么说吧。定义 \(id_1=1\),对于每个左部点 \(x\),定义 \(id_x=\max_{(p,x)}(id_p)+1\)。对于 \(u\),定义 \(id_u=cnt+1\)

我们来说明这个东西是拓扑序。考虑任意一个路径 \(s\to t\),对于路径上相邻两点 \((x,y)\),都有 \(id_y>id_x\)。所以这个是一个合法的拓扑序。

后面的东西都可以简单得出。

所以我们只要做一个区间 chkmn,然后查询一些单点值就行了。这个东西可以单 log。

CF464E

给无向图,边权都是 \(2^x\),求 \(s\to t\) 最短路。

\(n,m,x\le 2\times10^5\)

我们发现正常的 dij 其实是可以跑的,但问题是我们要写高精度,这个就不太好了。

注意到 dij 过程当中,我们其实对 \(dis\) 只有两种操作:比较大小,加 \(w\)

我们维护二进制串,每次操作有区间赋 0 和单点修改,以及比较两棵线段树的大小。后者可以 hash。

CF543E

我们建一棵主席树,然后每次 x 增加的时候就进行一个区间加,查询就是一个区间最小值。

但是建不得,因为这个题卡空间。

看不懂/ng。

[NOI Online #2 提高组] 游戏

考虑到这个恰好 \(k\) 对非常难受,所以我们二项式反演一下,转为计算所谓的钦定。

\[f_k=\sum_{i=k}^n\binom{i}{k}ans_i\iff ans_i=\sum_{i=k}^n(-1)^{i-k}\binom{i}{k}f_i \]

那么,我们考虑这个 \(f\) 怎么算,显然可以树形 dp。

那就做完了。

[MtOI2018] 情侣?给我烧了!

这一类题暂时没什么能说的。我们这里只写一下式子。

\[\begin{aligned} ans_k&=\sum_{i=k}^n(-1)^{i-k}\binom{i}{k}\binom{n}{i}\binom{n}{i}i!(2n-2i)!2^i\\ &=2^k\frac{(n!)^2}{k!}\sum_{i=0}^{n-k}(-1)^i\frac{(2(n-k-i))!}{((n-k-i)!)^2i!}2^i \end{aligned} \]

注意到,后面那一项只跟 \(n-k\) 有关系,所以我们预处理即可。总复杂度 \(O((T+n)n)\)

注意到后面那一项可以写成卷积的形式,所以我们也可以 \(n\log n\) 预处理。

对于加强版,我们考虑另外一个组合意义。考虑这个问题对应的错排 \(D_n\)

那么最后的答案 \(ans_{n,k}=\binom{n}{k}\binom{n}{k}k!2^kD_{n-k}\)

考虑错排的递推式,这是非常类似的。\(D_n=2n(2n-2)(D_{n-2}(2n-2)+D_{n-1})\)

[TJOI2019] 唱、跳、rap和篮球

这个我们上来第一个想法是直接 dp,发现状态不好记,那就算了。

第二个想法是容斥,如果使用 dp 实现的话会陷入同样的困境,所以我们不妨直接枚举有 \(k\) 个不合法段,然后你发现你并不能枚举这个东西,你只能钦定。那我们套一个二项式反演就行了。

\[\begin{aligned} &lim=\min(a,b,c,d,\frac{n}{4})\\ ans&=S(a,b,c,d,n)-\sum_{k=1}^{lim}f_k\\ &=S(a,b,c,d,n)-\sum_{k=1}^{lim}\sum_{i=k}^{lim}(-1)^{i-k}\binom{i}{k}\binom{n - 3i}{i}g_i\\ &=S(a,b,c,d,n)-\sum_{k=1}^{lim}\sum_{i=k}^{lim}(-1)^{i-k}\binom{i}{k}\binom{n - 3i}{i}S(a-i,b-i,c-i,d-i,n-4i) \end{aligned} \]

然后你发现 \(S(a,b,c,d,n)\) 再 dp 又要爆爆爆。

忍不了了,直接容斥!

容斥不了,再反演!

反演不了,寄了!

没关系,我们看一眼 sol。

这里说 \(S(a,b,c,d,n)=n![x^n]F_aF_bF_cF_d\),其中 \(F_p=\sum \frac{x^i}{i!}\),所以我们可以 NTT 在 \(n\log n\) 时间内求出解。

同样,注意到我们要算的本质不同的 \(S\) 只有 \(O(n)\) 种,所以我们可以 \(O(n^2\log n)\) 预处理。

总复杂度 \(O(n^2\log n)\)

但是我们还可以更好一点。因为我们要算的参数是特殊的,相当于每次在最后额外加了一项,那我们可以这么算卷积。

\[F_aF_b=(F_{a-1}+X_a)(F_{b-1}+X_b)=F_{a-1}F_{b-1}+X_aF_{b-1}+F_{a-1}X_b+X_aX_b \]

后面三项可以 \(O(n)\) 计算。这样,我们计算前两个和后两个的卷积,需要答案的时候,暴力 \(O(n)\) 算即可。

复杂度 \(O(n^2)\)

同时注意到另外一种有意思的做法。

我们设 \(dp_{a,b,n}\) 表示上限为 \(a,b\) 时拼出 \(n\) 个方案数,这个可以 \(O(n^3)\) dp。我们算 \(S(a,b,c,d,n)\) 时,可以枚举 \(a,b\) 一共用了多少个,然后就可以算了。复杂度 \(O(n^3)\)

[CTS2019] 随机立方体

这个题我之前听课听到过。

首先,恰好 \(k\) 个很讨厌,我们改成钦定 \(k\) 个。

然后,你考虑现在在这个立方体里面,有 \(k\) 个位置被钦定了,然后你要算方案数。你发现这个方案数 \(g_k\) 其实只和 \(k\) 有关,跟你具体钦定哪几个位置没关系。这样我们就有了算的基础。

那我们不妨假设这几个点从左下角开始往右上方堆。你要算这个的方案数。你列一列这个大小关系,发现还是很困难。我们考虑钦定这 \(k\) 个数的大小关系,你发现这个关系会形成一棵树的样子,并且在钦定的情况下,这个关系和原来的关系是等价的。所以我们枚举大小关系,因为不同大小关系的答案是一样的,所以最后效果就是乘了 \(k!\)

现在,你手里有一棵叶向树,你要统计它的拓扑序。这个是经典问题,答案是 \(n!\prod\frac{1}{sz_u}\),而这棵树的形态我们比较清楚,每个点的 sz 也是清楚的,所以就可以做了。

\[\begin{aligned} &lim=\min(n,m,l)\\ ans_k&=\sum_{i=k}^{lim}(-1)^{i-k}\binom{i}{k}g_i\\ &=\sum_{i=k}^{lim}(-1)^{i-k}\binom{i}{k}\binom{n}{i}\binom{m}{i}\binom{l}{i}(i!)^3(nml-(n-i)(m-i)(l-i))!((n-i)(m-i)(l-i))!\binom{nml}{(n-i)(m-i)(l-i)}\prod\frac{1}{sz_u} \end{aligned} \]

这个阶乘非常吓人。但是我们要算的是概率,也就是说方案数最后还要除以 \((nml)!\),所以这一堆就无了。

[ZJOI2022] 树

我们设 \(f_1(S),f_2(S),g_1(S),g_2(S)\),其中 \(f\) 表示非叶子恰好是 \(S\)\(g\) 表示非叶子是 \(S\) 的子集。

那也就是说,\(g_i(S)=\sum_{T\subseteq S}f_i(T)\),我们可以简单反演得到 \(f_i(S)=\sum_{T\subseteq S}(-1)^{|S|-|T|}g_i(T)\)

我们要算的是:

\[\begin{aligned} ans&=\sum_{S}f_1(S)f_2(\bar{S})\\ &=\sum_{S}(\sum_{T\subseteq S}(-1)^{|S|-|T|}g_1(T))(\sum_{T\subseteq \bar{S}}(-1)^{|\bar{S}|-|T|}g_1(T))\\ &=\sum_{S}\sum_{T_1\subseteq S}\sum_{T_2\subseteq \bar{S}}(-1)^{|S|+|\bar{S}|-|T_1|-|T_2|}g_1(T_1)g_2(T_2)\\ &=\sum_{T_1}\sum_{T_2}(-1)^{n-|T_1|-|T_2|}g_1(T_1)g_2(T_2)\sum_{T_1\subseteq S\land T_2\subseteq\bar{S}}1\\ &=\sum_{T_1}\sum_{T_2}(-1)^{n-|T_1|-|T_2|}g_1(T_1)g_2(T_2)2^{n-\text{popcount}(T_1\cup T_2)}[T1\cap T_2=\emptyset]\\ &=\sum_{T_1\cap T_2=\emptyset}(-1)^{n-|T_1|-|T_2|}g_1(T_1)g_2(T_2)2^{n-|T_1|-|T_2|} \end{aligned} \]

非常酷!

我们考虑怎么去算一个 \(g_i(S)\)。这个就是考虑 \(S\) 的前缀和,然后我们乘乘乘就行了。

考虑我们怎么去算上面那个东西。你使用一个 dp,\(dp_{i,j,k}\) 表示现在考虑到了第 \(i\) 位,然后目前的前缀和是 \(j,k\)。但是你发现有一个问题,就是说我们算 \(g_2(S)\) 的时候,每次乘的数应该是 \(pre_n-pre_{i-1}\) 这种东西,所以我们可能还得提前知道 \(pre_n\) 是谁,如果记录下这个再做的话就是 \(O(n^4)\),非常不好。

呃呃,瞄了一眼 sol。

我们发现刚刚有点唐。你既然 \(g_2\) 计算要用到后缀和,那你就记 \(k\) 是后缀和就行了。或者从另一种视角看,你的所有涉及到 \(k\) 的都会和 \(pre_n-k\) 一起出现,那你不妨直接记 \(pre_n-k\),这样就是 \(O(n^3)\) 了。

实现有一些细节。

[NOI2019] 机器人

这个感觉有点像 dp 套 dp,又有点拉格朗日插值的感觉。我之前应该做过。

我们先想一个 dp 出来。你发现按照序列的顺序 dp 是非常困难的,但是按照值域来 dp 是很轻松的。那我们设 \(dp_{l,r,v}\) 表示只考虑 \([l,r]\),并且额外要求每个值 \(\le v\) 的方案数。

我们枚举这个区间的最后一个最大值出现在什么地方。容易知道,这个值大概在序列的中间,不会偏太多。同时,最大值自然把问题分割成子问题。

\[dp_{l,r,v}=\sum_{pos}\sum_{val=A_{pos}}^{\min(v,B_{pos})} dp_{l,pos-1,val}dp_{pos+1,r,val-1} \]

如果直接实现这个 dp,我们大概可以分析出一个 \(O(n^2V^2)\) 的界。我们事实上可以进行一个前缀和优化。我们设 \(f_{l,r,v}\) 表示这个区间最大值恰好是 \(v\),那么我们从 \(dp\) 转移到 \(f\) 是简单的,从 \(f\) 求和得到 \(dp\) 也是简单的。这样复杂度是 \(O(n^2V)\)

然后我们通过查询题解实验得知,合法的 \((l,r)\) 也就 2500 左右。我们复杂度分析可以改进为 \(O(mV)\)

现在最大的问题是我们的复杂度跟值域相关,而原问题值域过大。我们现在有一些选择:另寻他法,离散化,拉格朗日插值。

这个方法看起来就很对,所以我们多往下想几步。

呃呃好麻烦啊,看了 sol。

我们注意到,这个 \(dp_{l,r}\) 是关于 \(v\) 的分段多项式,而你注意到这个分段操作的端点一定是这个“变化点”,也就是 \(A_{pos},B_{pos}+1\),那我们就容易发现多项式分段不会超过 \(r-l+1\) 段,并且次数应该也不高,可以暴力维护。

另外一个视角其实是等价的,我们考虑通过插值的方法来找出这个多项式。

还看到另外一个有趣的做法。对于 \(A_i=1,B_i=1e9\) 的时候,我们考虑钦定当前选出了 \(k\) 个数作为最终的答案,然后算个 dp 就行了,最后二项式反演一下。但是我不懂啊,怎么推广到原题的。哦,是不是只把在这个值域区间里的离散化,感觉有些道理。

理解不是很充分。

[六省联考 2017] 组合数问题

\[\begin{aligned} ans&=\sum_{i=0}^{nk}\binom{nk}{i}[i\equiv r(\bmod \ k)]\\ &=\sum_{i=0}^{nk}\binom{nk}{i}[k\mid (i-r)]\\ &=\sum_{i=0}^{nk}\binom{nk}{i}\sum_{j=0}^{k-1}w_k^{(i-r)j}\\ &=\sum_{j=0}^{k-1}w_k^{-rj}\sum_{i=0}^{nk}\binom{nk}{i}w_k^{ij}\\ &=\sum_{j=0}^{k-1}w_k^{-rj}(1+w_k^j)^{nk} \end{aligned} \]

这个随便做一做就好了。看起来很酷,但问题是我们要做的是模 p 意义下,在这个意义下不一定有 \(k\) 次单位根。但是我们可以做循环卷积。对 \((1+x)^{nk}\) 做长度为 \(k\) 的循环卷积就行了。卷积可以暴力。

另外一个做法是考虑组合意义,然后矩阵加速即可。这两个本质相同。

[省选联考 2022] 填数

你考虑计数 \([vl,vr]\) 值域区间的答案,这个可以 \(O(n)\) 做一次。我们做 \([vl,vl+k]-[vl+1,vl+k]\) 即可得到 \(mn=vl\) 的答案,然后我们做 \(V\) 次就可以得到答案。复杂度 \(O(nV)\)

考虑到,我们的这个值域区间,它在大多数情况下,平移一格,每个位置只会导致 1 的变化。或者说,在一个区间内,每个点的贡献可以写成多项式,然后我们答案事实上是若干多项式乘起来。所以我们拉格朗日插值即可。

Luogu P8558

看了 sol,但是这个题好像并不是很难,给的条件都挺好的,没有故意恶心你。

我们先明确一下,我们研究的对象是路径,这路径总是以 \((A,B,C)\) 为起点,以一个出界点结束。所以这路径不是等长的。

我们好奇的是出界时走的路径长度,而路径长度事实上是曼哈顿距离,这个只与你出界点的坐标有关。我们事实上只需要计算走到每个出界点的概率。

出界点肯定是由一个边界点走来的,也就是说我们需要计算走到每一个边界点的概率。这可以尝试推导组合意义,但我们不妨使用生成函数。因为这个过程是对称的,我们不妨假设起点是 \((0,0,0)\) 去算到达 \((x,y,z)\) 的概率。

\[F(x,y,z)=\frac{1}{3}(x+y+z)f(x,y,z)+1\\ F(x,y,z)=\frac{1}{1-\frac{1}{3}(x+y+z)}\\ [x^ay^bz^c]F(x,y,z)=(\frac{1}{3})^{a+b+c}\binom{a+b+c}{a,b,c} \]

呃呃,这个好像挺显然的。

没事。我们接下来以 \(z=0\) 的边界点为例,推一下式子。

\[\begin{aligned} ans_z&=\sum_{x=0}^A\sum_{y=0}^B\frac{1}{3}f(A-x,B-y,0)(x+y)^k\\ &=\sum_{x=0}^A\sum_{y=0}^B\frac{1}{3}(\frac{1}{3})^{A+B+C-x-y}\binom{A+B+C-x-y}{A-x,B-y,C}(x+y)^k\\ &=(\frac{1}{3})^{C+1}\sum_{s=0}^{A+B}(\frac{1}{3})^s(A+B-s)^k\sum_{x=s-B}^A\binom{s+C}{x,C,s-x}\\ &=(\frac{1}{3})^{C+1}\sum_{s=0}^{A+B}(\frac{1}{3})^s(A+B-s)^k\binom{s+C}{C}\sum_{x=s-B}^A\binom{s}{x} \end{aligned} \]

后面这个东西,拆一拆,大概可以变成一个 NTT 的形式,所以我们应该可以 \(O(n\log n)\) 求解。

但是 sol 里有一种更好的做法。

\[\begin{aligned} f(s)&=\sum_{x=s-B}^{A}\binom{s}{x}\\ &=\sum_{x=s-B}^A(\binom{s-1}{x-1}+\binom{s-1}{x})\\ &=2f(s-1)-\binom{s-1}{A}-\binom{s-1}{B} \end{aligned} \]

这样我们就可以递推这个东西了。好像具体数学上面有讲这部分“超几何式”的内容,可以改天看看。

我们这里写 NTT 做法,看看对不对。好像很难卡过去,还是写递推吧。

[TJOI2015] 概率论

呃呃,怎么这个题不会做啊。

我看到题,第一个想法是觉得这个本质不同的等概率生成有点烦,所以我想找一个随机的过程,使得最后本质不同的是等概率生成的。然后并没有思路。

然而事实上概率是假的,我们算 \(\frac{f_n}{g_n}\) 就行了,\(g_n\) 是典中点 Catlan 数。

\(f_n=\sum_{i=0}^n g_if_{n-i-1}+g_{n-i-1}f_i=2\sum_{i=0}^nf_ig_{n-i-1}(n\ge 2)\)

也就是说 \(F=2xFG+x\),也就是 \(F=\frac{x}{1-2xG}=\frac{x}{\sqrt{1-4x}}=x\sum_{k}\binom{-\frac{1}{2}}{k}(-4x)^k\),也就是说 \(f_n=\binom{2n-2}{n-1}\),而 \(g_n=\frac{\binom{2n}{n}}{n+1}\),所以 \(ans=\frac{n(n+1)}{2(2n-1)}\)

Luogu P1654

这个题一看就会,但是我们想把背后的过程写得严谨一些,不然总感觉这个概率非常神奇。

我们定义 \(V_n\) 是这个随机过程产生的 01 序列,并且定义 \(X\) 是分数的随机变量。我们考虑强制令 \(p_{n+1}=0\),显然这不会改变 \(X\)

定义

\[X_i=\begin{cases} 0&,V_i=1\\ i-1所在连续段的分数&,V_i=0 \end{cases} \]

那么有 \(X=\sum X_i\)。注意到我们实质上是规定每个段的贡献在下一个位置计算。

那么我们可以单独计算 \(E(X_i)\)

\[E(X_i)=\sum_{k} k^3Pr(X_i=k^3) \]

直接做这个东西,我们可以得到一个 \(O(n^2)\) 的做法。这什么用都没有。

我们重新定义。

\[X_i=\begin{cases} 0&,V_i=0\\ X_{i-1}+1&,V_i=1 \end{cases}\\ Y_i=\begin{cases} 0&,V_i=0\\ Y_{i-1}+2X_{i-1}+1&,V_i=1 \end{cases}\\ Z_i=\begin{cases} 0&,V_i=0\\ Z_{i-1}+3Y_{i-1}+3X_{i-1}+1&,V_i=1 \end{cases}\\ X'_i=\begin{cases} 0&,V_i=1\\ X_{i-1}&,V_i=0 \end{cases} \]

\(Y'_i,Z'_i\) 类似定义。

我们想求的其实就是 \(E(Z)=\sum E(Z'_i)\)。然后你发现还是没啥用。我们不妨求一个前缀和。

\[Z_i=\begin{cases} Z_{i-1}&,V_i=0\\ Z_{i-1}+3Y_{i-1}+3X_{i-1}+1&,V_i=1 \end{cases} \]

注意我们并不修改 \(X,Y\) 的定义。我们现在要求的就是 \(E(Z_n)\)

\[E(Z_n)=\begin{cases} E(Z_{n-1}|V_n=0)Pr(V_n=0)&,V_n=0\\ E(Z_{n-1}|V_n=1)Pr(V_n=1)+3E(Y_{n-1}|V_n=1)Pr(V_n=1)+3E(X_{n-1}|V_n=1)Pr(V_n=1)+1Pr(V_n=1)&,V_n=1 \end{cases} \]

而我们知道 \(V_n\) 的值跟前面是独立的,所以我们可以递推。

这种题好像可以有一个技巧转化成非概率类题目。你考虑这个题,你就考虑成每个点有选和不选两种情况,对于最后的每种情况有一个函数来赋值,然后让你算值的和。如果这个会做了,那再带个权就是概率的做法。

[SHOI2014] 概率充电器

我们先想不分概率的情况。或者说,想所有概率都是相等的情况。

\(dp_{u,0/1,0/1}\) 表示 \(u\) 子树内,这个子树的根所在连通块没/有被点亮,这个子树的根的连通块不算/算入答案中时的答案,\(cnt_{u,0/1}\) 表示方案数。

不想写 dp 式子了,反正稍微想一下就行了。你把每个子树的贡献,乘上别的子树的方案数,然后再加上根的贡献。

接下来我们考虑概率。你发现这个题等价于求 \(\sum Pr(i)\) 但是这毫无卵用,因为 \(Pr(i)\) 并不好求。

那我们还是老老实实考虑怎么把上面那个 dp 改成概率的形式。

定义 \(cnt_{u,0/1}\) 为仅考虑 \(u\) 子树中的选择情况时,根所在连通块没/有被点亮的概率。容易发现 \(cnt_{u,0}+cnt_{u,1}=1\)

定义 \(dp_{u,0/1,0/1}\) 为仅考虑 \(u\) 子树中的选择情况时,分类记根所在连通块没/有被点亮,这个子树的根的连通块不算/算入答案中时的期望。也就是说我们其实有两种随机变量 \(X_{u,i},Y_{u,i}\)\(dp_{u,0/1,0}\) 算的是 \(X_{u,i}\) 的期望,\(dp_{u,0/1,1}\) 算的是 \(Y_{u,i}\) 的。

\[\begin{aligned} cnt_{u,0}&=Pr(V_u=1)Pr(u不亮|V_u=1)+Pr(V_u=0)Pr(u不亮|V_u=0)\\ &=Pr(V_u=0)Pr(u不亮|V_u=0)\\ &=Pr(V_u=0)\prod_v Pr(v不亮或者uv不连通|V_u=0)\\ &=Pr(V_u=0)\prod_v Pr(v不亮 \cup uv不连通)\\ &=Pr(V_u=0)\prod_v Pr(v不亮)+Pr(uv不连通)-Pr(v不亮\cap uv不连通)\\ &=Pr(V_u=0)\prod_v Pr(v不亮)+Pr(uv不连通)-Pr(v不亮)Pr(uv不连通)\\ \end{aligned} \]

\(cnt_{u,1}\) 直接减一下就行了。

\[\begin{aligned} dp_{u,0,0}&=\sum_{v\in subtree(u)} E(X_{u,v})[u不亮]\\ &=\sum_{v\in son(u)}\sum_{p\in subtree(v)} [u不亮]E(X_{u,p})\\ &=\sum_{v\in son(u)}\sum_{p\in subtree(v)} [u不亮且uv连通]E(X_{u,p})+[u不亮且uv不连通]E(X_{u,p})\\ &=\sum_{v\in son(u)}\sum_{p\in subtree(v)} [其它t对u无影响且uv连通且v不亮]E(X_{u,p})+[其它t对u无影响且uv不连通]E(X_{u,p})\\ \end{aligned} \]

然后基本上就可以拆开成子问题了。这个题其实没啥概率味,就是硬生生加权而已。

[PKUWC2018] 随机游走

给一棵树,每次随机选一条出边走过去,固定起点 \(x\)。多次询问,给一个集合 \(S\),问从 \(x\) 出发期望走多少步可以覆盖 \(S\)

\(n\le18,Q\le5000\)

我们设 \(E_{u,T}\) 表示在已经覆盖了集合 \(T\),目前处在 \(u\) 位置的前提下,期望走多少步覆盖 \(S\)

那显然有

\[E_{u,T}=[S\not\subseteq T](\sum_{v}\frac{E_{v,T\cup\{v\}}}{deg_u}+1) \]

证明可以考虑把左边的式子拆开,然后对于每个路径,按第一条边分类,然后用独立性把第一条边拆出来,就行了。

那我们显然可以高斯消元解这个东西,每次分开做,复杂度 \(O(Q2^{3n})\)

这很不好,不好的一个原因在于,我们每次都单独算。为什么要单独算呢?因为每次的终点不一样,所以整个 E 的值都不同,只能单独算。但是我们每次的起点都是 \(E_{x,\{x\}}\),我们能不能算一算 \(dp_{v,S}\) 表示从起点第一次走到这里的期望步数呢?

这个似乎没那么好算。

我们考虑 minmax 容斥。

\[f_{u,S}=[u\not\in S]\sum_v \frac{f_{v,S}}{deg_u}+1 \]

看了 sol。

我们考虑套路,把 \(f_{u,S}\) 写成关于 \(f_{fa,S}\) 的线性形式。设 \(f_{u,S}=A_uf_{fa,S}+B_u\)。这个想法,是基于首先对所有叶节点而言,这个是自然的。然后就是说,你考虑一个子节点都是叶节点的点,你把它的儿子写成关于它自己的线性形式,然后再牵扯上自己的 fa,那么它也可以写成这种形式。本质上还是高斯消元。

而对于根节点而言,它没有父亲,它消元之后 \(f_{rt,S}=B_{rt}\)

我们重新写一下方程。

\[f_{u,S}=\frac{1}{deg_u}(f_{fa,S}+\sum_{v\in son(u)} A_vf_{u,S}+B_v)+1\\ (deg_u-\sum_{v\in son(u)}A_v)f_{u,S}=f_{fa,S}+\sum_{v\in son(u)}B_v+deg_u\\ f_{u,S}=\frac{1}{deg_u-\sum_{v\in son(u)}A_v}f_{fa,S}+\frac{\sum_{v\in son(u)}B_v+deg_u}{deg_u-\sum_{v\in son(u)}A_v} \]

你可能会担心,如果 \(deg_u-\sum_{v\in son(u)}A_v=0\) 怎么办。事实上我们模拟的是高斯消元的过程,只要高斯消元能消出来,这个过程就不会有问题。

现在我们可以递推 \(A_u,B_u\) 了,然后再 dfs 一次就可以算出所有点的答案。

回答询问每次枚举即可。好像可以做到更优的复杂度。额,当然,高位前缀和就行了。

[BJOI2018] 治疗之雨

我们先考虑算出来一轮操作过后,第一个人血量变化为 \(x\) 的概率。

\[p_x=\frac{m}{m+1}\binom{k}{-x}(\frac{1}{m+1})^{-x}(\frac{m}{m+1})^{k+x}+\frac{1}{m+1}\binom{k}{-x+1}(\frac{1}{m+1})^{-x+1}(\frac{m}{m+1})^{k+x-1} \]

那么我们有

\[E_u=\sum_{x=-k}^1E_{u+x}p_x+1 \]

显然可以高斯消元。但是这个东西有点特殊,它向后最多只会连一条边。所以我们可以 \(O(n^2)\) 消元。具体一点,我们可以枚举到每个位置 \(p\) 的时候,计算它之前所有东西用 \(E_p\) 表示的系数。

[UNR #2] 黎明前的巧克力

这个典题当然是看过 sol 的啦。

你考虑它可以看作是对一个异或和为 0 的集合,分成两部分的方案数。那么,一个大小为 \(k\) 的集合会产生 \(2^k\) 贡献。

我们想算的是 \([x^0]\prod_{i=1}^n(1+2x^{a_i})\)

首先可以对每个分别进行 FWT,然后乘起来,最后 IFWT。你可以获得 0 分的好成绩。

考虑优化这个过程。发现 FWT 之后每个位置是 3 或 -1,然后我们假设有 \(x\) 个 3,那么这一位 FWT 之后乘起来就是 \(3^x(-1)^{n-x}\),我们最后 IFWT 回来即可。

问题是怎么算这个 \(x\)。你把所有东西加起来统一 FWT,我们知道 \(FWT(A+B)=FWT(A)+FWT(B)\),所以我们可以算出来这一位的系数和 \(s\),然后解方程可以得到 \(x=\frac{n+s}{4}\)

Luogu P7526

我们发现,如果没有选择 \(m\) 个的限制,那么这个直接 FWT 就做完了。但是这个限制去不得。

那我们手动去掉。我们对每个 \(a_i\) 算出 \(FWT(x^{a_i})\),然后对这 \(n\) 个序列,枚举其中的 \(m\) 个,乘起来,然后加起来。形式化来讲:

\[\sum_{p_1<\dots<p_m}\prod_{i=1}^mFWT(x^{a_{p_i}}) \]

那这个东西我们肯定不是暴力算的。你注意到 \(FWT(x^{a_{p_i}})\) 里只有 \(\pm 1\),所以我们肯定是想知道对于一个位置 \(k\) 而言,\(n\) 个序列 FWT 之后在这个位置上有几个 \(+1\) 几个 \(-1\)

你把式子写出来,你发现一个 \(FWT(x^a)\)\(k\) 位是 \((-1)^{|a\cap k|}\),我们根据套路直接求和之后再 FWT 即可。

那比方说我们知道了这一位有 \(x\)\(-1\)\(n-x\)\(+1\)

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

\[\begin{aligned} ans_k&=\sum_{i=\max(0,m-n+x)}^x\frac{x!}{i!(x-i)!}\frac{(n-x)!}{(m-i)!(n-x-m+i)!}(-1)^i\\ &=x!(n-x)!\sum_{i=\max(0,m-n+x)}^x\frac{(-1)^i}{i!(m-i)!(n-x-m+i)!}\frac{1}{(x-i)!} \end{aligned} \]

可以卷积。

[USACO23FEB] Problem Setting P

我们注意到这个东西排出来之后长得跟杨表似的,考虑设 \(f_S\) 表示这个杨表以 \(S\) 状态结束的方案数。

你去枚举这个 \(S\) 状态之前的状态是哪一个。

\[\begin{aligned} f_S&=\sum_{T\subset S}f_Tw_S\\ &=(\sum_{i=1}^{cnt_S}\binom{cnt_S}{i}i!)\sum_{T\subset S} f_T \end{aligned} \]

前面这个我们显然可以预处理。这时直接枚举子集的子集是 \(O(3^n)\),我们可以子集卷积得到 \(O(n^22^n)\),我们还可以在 dp 的同时做 FMT。具体来说,记 \(sum_{S,k}\),表示对所有 \(T\subseteq S\)\(T\)\(S\) 最多只有前 \(k\) 个会有不同求和。

[SNOI2022] 数位

这不是我们 zr 模拟赛的题吗?

首先这个上下都有界,非常讨厌,我们不妨直接给他 gank 了,变成 \([0,R-L]\),最后统一加上 \(kL\)

\(dp_{i,j,k,p}\) 表示目前考虑了最高的 \(i\) 位,进位是 \(j\),有 \(k\) 个数仍然顶上界,\(p\) 是当前数码已经到了几。

你预处理,\(cnt_{i,j,k,k'}\) 表示进位是 \(i\),这一位留下 \(j\),有 \(k\) 个数顶上界,有 \(k'\) 个数这次变得不顶上界的前提下有多少种凑出来的方案。

你发现我们有 \(i\le k,0\le j\le 9\),我们这个时候直接暴力 dp 是 \(O(\log V\times k\times k\times 10\times k\times k\times 10)\)

首先我们把上界也给容了,这样我们需要做 \(k\) 次 dp,每次只需要记录和是否达到上界,复杂度可以做到 \(O(k\times \log V\times k\times 10\times k\times 10)\)

然后我们观察转移方程,它大概是 \(dp_{i-1,\lfloor\frac{j+s+bias}{10}\rfloor,(j+s+bias)\bmod 10}cnt_s\to dp_{i,j,p}\)。然后你把 \(s\) 拆成个位数 \(s_0\) 加上更高位 \(10s'\),那么就有:

\[dp_{i-1,s'+\lfloor\frac{j+s_0+bias}{10}\rfloor,(j+s_0+bias)\bmod 10}cnt_s\to dp_{i,j,p} \]

你发现,当你确定下来 \(j,p,s_0\) 之后,前面的是一个连续的区间,所以我们可以预处理前面这一部分,具体来说,记

\[f_{i,t,p}=\sum_{j=0}^{k}dp_{i,t+j,p}cnt_{10j+t} \]

暴力预处理一次这个,复杂度是 \(10\times 10\times k\)。利用这个,\(dp_{i,j,p}=\sum_{s_0}f_{i-1,\lfloor\frac{j+s_0+bias}{10}\rfloor,(j+s_0+bias)\bmod 10}\),我们应该可以直接除以一个 \(k\)

这样总复杂度就是 \(O(k\times \log V\times k\times 10\times 10)\),应该是比较稳的。

但是根本不想也不会去写这个题,考场上看到了顶多打把上界容了的做法。

以及,在 sol 区里看到了我之前胡的做法,原来真有人写啊!

posted @ 2024-01-15 06:53  PYD1  阅读(5)  评论(0)    收藏  举报