2024.2 ~ 多少回忆的碎片 / 请不要坠落
2nd Ucup Stage 21: Delft
C
发现只要有一个字符出现两次,且存在一个点和他不共线,一直走三角形绕圈就 \(\infty\) 了。
于是只有两种情况:
- 有一个字符出现两次,但所有点都在一条直线上:答案为 \(2\)。
- 所有字符互不相同:答案为 \(1\)。
G
\(|w|\le 2\):\(|w|=1\) 答案为 \(n\),\(|w|=2\) 时若 \(w_1=w_2\) 则答案为 \(2(n-1)\),否则为 \(n-1\)。
\(|w|=3\):本质不同的 \(w\) 只有四种,分别形如 aaa
,aba
,aab
,abc
。
对于第一种只需算出长为 \(3\) 的路径个数,第二三种可以设一个形如 \(f(u,j,0/1)\) 表示只考虑 \(u\) 子树内的路径,\(u\) 自己取得是 a
还是 b
,\(u\) 的儿子里面有 \(j\) 个 a
这样的状态,同时多算一下 \(f(u,j,\cdot)-j\) 或者 \(f(u,j,\cdot)+j\) 的最值即可快速转移。由于 \(\sum |\text{son}(u)|=O(n)\) 因此复杂度不超过 \(O(n\log n)\),log 来自转移时的排序。
现在考虑 abc
,设 \(f(u,0/1/2)\) 表示 \(u\) 子树内,且 \(u\) 选 a/b/c
的最多路径数;同时可以设 \(F_u,G_u\) 表示 \(u\) 子树内选点,且要求 \(u\) 自己选 b
,且如果儿子里面有 \(j\) 个 a/c
就给最终的值加上 \(j\),这样算的最大贡献。
\(f(u,0),f(u,2)\) 都容易通过 \(F,G\) 做到 \(O(1)\) 转移,考虑 \(F,G\) 怎么算。发现相当于有三个序列 \(f(\cdot,0/1/2)\),需要给每个 \(v\) 选择一个 \(f(v,\cdot)\),如果有 \(x\) 个选了 \(0\),\(y\) 个选了 \(2\),那么最终的贡献是选出的数之和加上 \(x\times y\)。
考虑钦定 \(x\),然后给每个 \(f(v,2)\) 都加上 \(x\)。
我们维护 \(f(\cdot,1/2)\) 的决策,发现每一个的贡献形如一段前面平着,后面斜率为 \(1\) 的分段函数;我们先钦定所有决策都必须在 \(1/2\) 中做出,然后算出 \(f(v,0)-\max(f(v,1),f(v,2))\) 的前 \(x\) 大并强制切换至 \(0\) 即可。
这里可以分别维护常数和斜率为 \(1\) 这两个部分的决策形成的有序序列,维护两个指针表示当前做出的决策,每次会把斜率为 \(1\) 的那部分全局 \(-1\),然后把常数部分的一些决策移动到斜率为 \(1\) 的部分。可以发现第二种操作对指针的移动影响为 \(O(1)\),因此第一种操作我们暴力把斜率为 \(1\) 的部分的指针向前移动,指针移动的总次数就是均摊线性。只不过维护有序序列还需要带个 \(\log\)。
总的时间复杂度为 \(O(n\log n)\)。
E
考虑对一组 \(S,P\) 怎么算 \(F(S,P)\),发现可以贪心,每次找第一次出现 \(P\) 的位置,然后删掉这个位置往后考虑。这样,每个 \(S\) 就唯一对应到一个匹配方案上。
考虑枚举 \(P\) 并钦定匹配方案,算出能够匹配上这个方案的 \(S\) 的个数,发现如果钦定了 \(P\) 出现的相邻两个位置是 \(i,j\),那么首先需要 \(j\ge i+|P|\),并且 \([i+|P|,j)\) 这个区间内的每个位置都不能作为 \(P\) 的开头。
考虑容斥,钦定 \(A\) 中位置都出现了 \(P\),计算其容斥系数,即:
其中 \(\text{valid}(B)\) 为真当且仅当 \(B\) 中元素从小到大排序后,相邻元素的差 \(\ge m\)。
WC2024
T2 - 水镜
注意到我们只关心 \(h_i,2L-h_i\) 和 \(h_{i+1},2L-h_{i+1}\) 之间两两的大小关系。当两个数的选择分别为 \((h_i,h_{i+1})\) 或者 \((2L-h_i,2L-h_{i+1})\) 时,这两个数的大小关系都和 \(L\) 无关;否则这只和 \(2L\) 与 \(h_i+h_{i+1}\) 的大小关系有关。
由于一共只有不超过 \(n-1\) 种不同的 \(h_i+h_{i+1}\),因此本质不同的 \(L\) 至多只有 \(n\) 种。枚举 \(L\) 的取值,考虑一个区间在确定了 \(L\) 的取值之后该如何判定是否合法。
仍然是考虑 \(h_i,2L-h_i,h_{i+1},2L-h_{i+1}\) 这四个数之间的大小关系。不妨先来考虑 \(h_i\neq h_{i+1}\) 的情形,记这四个数分别为 \(a_1,a_2,b_1,b_2\),由于我们一定可以调整 \(L\) 使得 \(2L\neq h_i+h_{i+1}\),这样,这四个数的大小关系就要么是 \(\min(b_1,b_2)<\min(a_1,a_2)<\max(a_1,a_2)<\max(b_1,b_2)\),也就是 \(b\) 的取值把 \(a\) 夹在中间;要么是 \(a\) 的取值把 \(b\) 夹在中间。
我们把这两种分别记为 \(\{2,3\}\to \{1,4\}\) 和 \(\{1,4\}\to \{2,3\}\)。如果是前者,不管前面取 \(2\) 还是 \(3\) 后面都只能取 \(4\);如果是后者,前一个必须取 \(1\) 否则直接无解,然后后一个一定会取 \(2\)。发现这要求区间必须形如先一段 \(\{1,4\}\to \{2,3\}\),然后是 \(\{2,3\}\to \{1,4\}\)。需要特殊考虑一下 \(h_i=h_{i+1}\) 的情况,这时一定前一个取较小值,后一个取较大值,那么要求 \(h_{i-1},h_i\) 形如 \(14/23\),\(h_{i+1},h_{i+2}\) 形如 \(23/14\)。
- 其实这就是官方题解得到的结论:\(p_i=\max(h_i,2L-h_i)\) 单谷。
考虑从小到大枚举 \(L\) 的取值,每个 \((i,i+1)\) 至多从 \(23/14\) 变成 \(14/23\) 一次,或者是反过来变一次。维护合法的极长连续段即可算出每个 \(i\) 向右最多延伸多少。一个更好写的写法是:套路地换个维度,倒着扫序列维,数据结构维护 \(L\) 那一维就只需要做区间覆盖和全局求 max 了。
QOJ8107
好像突然会做了!
首先显然需要 \(\frac{n(n-1)}{4}\in\mathbb Z\),即 \(n\equiv 0,1\pmod 4\)。
考虑 \(k=1\) 咋做,我们一路填 \(1,2,\cdots,x\),并保证 \(\frac{x(x-1)}{2}+x(n-x)\le \frac{n(n-1)}{4}\)。填到最大的 \(x\) 之后,我们先把后面依次填上 \(n,n-1,\cdots,x+1\),此时的顺序对数是 \(\frac{x(x-1)}{2}+x(n-x)\)。考虑算出还需要加 \(p\) 个顺序对,我们希望字典序尽可能小也就是 \(x+1\) 这个位置的数尽可能小,那么直接把 \(n-p\) 放到 \(x+1\) 这里来一定是最优的。
还需要说明 \(n-p\ge x+1\)。注意到 \(-\frac{x^2}{2}+(n-\frac{1}{2})x\) 当 \(x\leftarrow x+1\) 的时候会增加 \(n-x-1\),如果 \(n-p<x+1\),那么就有 \(n-x-1<p\),也就是说我们可以继续增加 \(x\),与之前的假设矛盾。
考虑 \(k=2\),显然 \(n\) 开始往后的都动不了,考虑能不能 \(p_{x+1}\leftarrow p_{x+1}+1\)。发现这恰好让顺序对少了一个,考虑交换 \(p_{x+2}\) 开始的任意相邻两个,发现就能消除影响。为了让字典序尽可能小,一定是交换 \(p_{x+2},p_{x+3}\)。
那 \(k\) 更大发现只需要改变这个交换的位置,如果发现交换一个已经凑不够 \(k\) 个了,就改为把 \(p_{x+1}\) 从最小解的基础上 \(+2\),然后后面交换两次相邻两项。
对于一般的情况,我们只需要求出字典序第 \(k\) 小的满足恰有 \(c\) 个顺序对的排列个数,并且 \(c\) 是 \(O(\log k)\) 级别。
注意此时 \(c\) 很小,直接从前往后填数即可。具体来说我们算出已填部分的顺序对个数,然后已填部分和未填部分产生的顺序对个数已经确定,于是只要求未填部分的顺序对个数恰好为 \(d\le c\),需要求出方案数。提前预处理即可。时间复杂度 \(O(n\log k)\),实际上 \(\log\) 的底数应该很大,感觉是 \(n\) 级别。
luogu 月赛
E
设 \(f(i,j)\) 表示前 \(i\) 个数分成 \(j\) 个区间,经典结论是对每个 \(i\),都有 \(f(i,j)\) 关于 \(j\) 上凸。
注意到 \(f(i,j)\le i\),考虑 \(\Delta(i,j)=f(i,j)-f(i,j-1)\),发现由于 \(\sum_{j=2}^i\Delta(i,j)=f(i,i)=i\),所以不同的 \(\Delta(i,\cdot)\) 只有 \(2\sqrt{i}\) 种。直观上来说就是,\(f(i,j)\) 关于 \(j\) 会形成 \(2\sqrt{i}\) 段直线。
考虑一条斜率为 \(k\) 的直线,发现当横坐标是 \(n/k\) 的时候他就已经超出 \(n\) 了,所以我们取阈值 \(B\),对下标 \(\le B\) 的和斜率 \(\le \frac{n}{B}\) 的分别算,就是 \(O(n\sqrt{n}\log n)\)。
注意到算一次是后缀加,查询全局 max,并查集配合单调栈维护即可做到 \(O(n\sqrt{n}\alpha(n))\)。
2024.2.15
A
只关心每个数的正负号;进一步这只和奇偶性有关。
- 对于偶数:
-
- 如果有至少两个奇数,那么偶数可以取遍所有 \(2^{cnt}\) 种正负号
-
- 如果奇数的个数 \(=1\),那么至少要有一个
+
号。
- 如果奇数的个数 \(=1\),那么至少要有一个
-
- 如果奇数的个数 \(=0\),那么正负号都至少有一个。
- 对于奇数:
- 不管怎样,都可以取遍 \(\lfloor n/2\rfloor\) 个负号的情形。
DP,\(f(i,j,0/1,0/1,s)=0/1\) 表示前 \(i\) 个数,奇数取了 \(j\) 个负号,偶数是否至少取了一个正号/负号,和能否到达 \(s\)。
转移:
- \(a_i\) 为偶数:\((j,c,d,s) \to (j,1,d,s+a_i),(j,c,d,s) \to (j,c,1,s-a_i)\)
- \(a_i\) 为奇数:\((j,c,d,s) \to (j,c,d,s+a_i),(j,c,d,s) \to (j+1,c,d,s-a_i)\)
这样状态数是 \(O(n^3a)\),注意到转移形式简单,bitset 优化即可做到 \(O(\frac{n^3a}{w})\)。
B
最优方案如果一个非叶子节点 \(u\) 上面连下来一条边,由于 \(u\) 一定至少要往下连一条,那么不如直接在之前合并的时候就直接把这条边连到下面去。所以最优情况一定是,每个点都往下连若干条到叶子节点的边。
直接 DP:\(f(u,j)\) 表示 \(u\) 子树内,留一个权值为 \(j\) 的叶子上去匹配的最小权值。转移形如选一个 \(u\) 的儿子 \(v\),继承 \(f(v,j)\),对于其他的直接算出 \(\min f(x,k)+k\times C_u\)。
考虑李超树维护这一堆直线,那么需要支持把 \(f_v\) 里面的直线全部往上平移,然后还要合并两个李超树。对于平移考虑维护个标记发现容易下传和维护;合并就在合并的时候比较出来较优的那个,把剩下的那个下传下去。
总复杂度 \(O(N\log N)\)。
C
构式二合一,只写了一半。。
考虑建出 ACAM 求出 \(f_u\) 表示 \(u\) 开始走到叶子的期望步数。转移很简单,但直接做是 \(O((nm)^3)\)。
这里有两个部分:
- 如何快速求出 \(f\)
- 如何快速定位到串 \(R\)
先说第二部分。注意到操作是后缀覆盖,考虑在 acam 上倍增一下即可求出从 \(x\) 开始,走 \(k\) 步字符 \(c\) 到达的节点。接下来使用颜色段均摊或者维护一个栈之类的东西即可快速定位。
然后说第一部分。tsx 讲了一个 \(O(n^3m)\) 的做法,大概是,注意到叶子结点的 \(f\) 是 \(0\),考虑从上往下,每次做到第 \(i\) 层的时候,我们假装已经求出第 \(i\) 层所有结点的 \(f\) 值(分别为 \(t_1,\cdots,t_k\)),然后用 \(t\) 把 \(1\cdots i-1\) 层的 \(f\) 表示出来。
考虑如何从第 \(i\) 层扩展到第 \(i+1\) 层,设第 \(i+1\) 层节点的 \(f\) 值分别是 \(u_1,\cdots,u_p\),考虑第 \(i\) 层的方程,发现 trie 树上的每条边要么深度严格减小,要么由父亲指向儿子。由此可以列出 \(t,u\) 之间的方程,\(O(n^3)\) 用 \(u\) 来表示出 \(t\)。这样往下做 \(m\) 层就做完了。复杂度是 \(O(n^3m)\)。
更好的做法:注意只有 \(n\) 个叶子,考虑做树链剖分,剖成 \(n\) 条链,以所有链顶为主元,考虑按照深度从小到大算出每个点的系数。唯一需要考虑的情况是 \(v\) 是 \(u\) 的儿子,且 \(u,v\) 在一条链上的情形。这种情况下,设 \(v=to(u,w)\),把 \(f_u=1+\sum_{c}p_cf_{to(u,c)}\) 反过来得到
由于 \(to(u,c)\) 要么是链顶,要么是深度更小的点,因此可以直接算出 \(f_v\)。这样就可以做到 \(O(n^3)\)。
2024.2.16
洛谷月赛 F
以下结论均为找规律得出。
\(s=1\):有 \(ans_n=ans_{n-1}\times f(n)\),其中 \(f(n)\) 是满足 \(\text{lcm}(x_1,\cdots,x_t)=n,\gcd(x_1,\cdots ,x_t)=1\) 的序列 \(x\) 的个数。显然这是积性函数,有
显然答案就是 \(\prod_{p,k}(f(p^k))^{\lfloor n/p^k\rfloor}\),分 \(k\ge 2\) 和 \(k=1\) 计算,\(k\ge 2\) 时 \(p\le \sqrt{n}\) 暴力枚举即可;\(k=1\) 时只需要算质数个数,随便写一个筛就行。
\(t=1\):\(n\) 稍微大一点 \(ans\) 就是 \(0\) 了。
\(t=2\):仍然考虑 \(ans_n=ans_{n-1}\times f(n)\),此时的 \(f\) 也是积性函数,有
\(t>2\):\(f\) 仍为积性函数。不过 \(k=1\) 时实际上是 \((s+1)^t-2\),\(k\ge 2\) 我也不知道是啥玩意。
仔细找一下发现,对于一个确定的 \(s\),\(f(p^k)\) 仍然和 \(p\) 无关,但是是一个关于 \(k\) 的 \(t\) 次多项式?所以可以做 \(t\le 9\),就是拉插一下然后就能都算出来了。
下面来正经做法,顺便证明一下上面的若干结论。
考虑 \(f(n)=\sum_{d\mid n}\mu(d)(\sigma_0(d^s))^t\),它就是 \(g(d)=(\sigma_0(d^s))^t\) 的高维差分,这是积性函数,考虑到
那么
现在考虑算行列式。把 \(f\) 再做高维差分,设 \(f(n)=\sum_{d\mid n}h(d)\),那么
设 \(b_{i,j}=[j\mid i],c_{i,j}=[i\mid j]h(i)\),那么 \(a_{i,j}=\sum_{d=1}^n b_{i,d}\times c_{d,j}\)。
设这三个矩阵分别为 \(A,B,C\),那么 \(A=B\times C\),其中 $\times $ 是矩阵乘法。
于是 \(\text{det}(A)=\text{det}(B)\times \text{det}(C)\),注意 \(B,C\) 均为上三角或下三角矩阵,于是有:
- \(\text{det}(B)=1\)
- \(\text{det}(C)=\prod_{i=1}^nh(i)\)
只需要算 \(\prod_{i=1}^nh(i)\)。考虑枚举 \(p^k\) 算贡献,有
对于 \(k\ge 2\) 有 \(p\le \sqrt{n}\),枚举每个 \(p\) 算一下贡献,注意到快速幂只需要算 \(O(\log n)\) 个数的 \(t\) 次幂,于是这部分复杂度可以做到 \(O(\sqrt{n}+\log n\log t)\);对于 \(k=1\) 的部分只需要算素数个数。
怎么算素数个数:注意到合数都满足最小质因子 \(LPF(i)\le \sqrt{n}\),设 \(G_k(n)\) 表示 \(n\) 以内满足最小质因子 \(> p_k\) 或者是质数的数个数(也就是埃氏筛筛完 \(p_k\) 之后剩下的数个数),考虑递推
- 对于 \(n< p_k^2\),显然 \(G_k(n)=G_{k-1}(n)\)
- 对于 \(n>p_k\),新删掉了一部分合数,这些合数都是 \(p_k\) 的倍数,我们考虑取出 \(\le \lfloor n/p_k\rfloor\) 且最小质因子 \(>p_{k-1}\) 的所有数,把它们全都乘上 \(p_k\),那么就可以得到最小质因子为 \(p_k\) 的数。考虑这样的数有多少个,发现就是 \(G_{k-1}(\lfloor n/p_k\rfloor)-(k-1)\)。(注意我们 \(G\) 的定义里面包含质数因此要减掉)其实对于一般的 min25 筛应该写作 \(G_{k-1}(p_{k-1})\)。
这里有一个空间上的细节:考虑滚动数组,对 \(\le \sqrt{n}\) 的直接记录 id,大的记录 \(n/i\) 的 id,每次滚一层的时候,直接找所有 \(\lfloor n/i\rfloor \ge p_k^2\) 的去重新算,这样算一次复杂度是 \(\le n/p_k^2\) 的基本和组内元素个数。
对 \(p_k^2<\sqrt{n}\) 的,有 \(n/p_k^2>\sqrt{n}\),这部分我们直接估计成 \(\sqrt{n}\),那么这部分复杂度 \(O(\pi(n^{0.25})\times \sqrt{n})=O(n^{0.75}/\log n)\);否则我们估计成 \(n/p_k^2\),这部分也是 \(O(n^{0.75}/\log n)\)。
你发现这其实也证明了复杂度,太牛!
2024.2.21
我咋挂成狗了?
A
根号分治,质因子分成两半,前半部分和后半部分分别做一下
指数没 \(+1\) 导致 RE 了。。。真弱智
B
相当于要求所有以 \(s\) 开始,\(t\) 结束的路径 \(P\),计算 \(f(P)\times \prod w(P_{i-1},P_i)\) 之和还有平方和。
其中 \(f(P)\) 表示最后一条 \(0\) 边后面的边数,\(w(x,y)=\frac{1}{\deg_x}\) 表示这条边的概率。
把边倒过来,变成以 \(t\) 开始,到 \(s\) 结束,只不过 \(t\) 只能在开头经过一次(为了满足这个条件,只需要在一开始把图中 \(t\) 的出边删掉),\(s\) 可以经过多次,只不过终点必须是 \(s\)。
于是设 \(dp(i,0/1/2)\) 表示走到 \(i\) 的 \(0/1/2\) 次幂和,唯一特殊点是:
- \(dp(s,0)\) 需要多加一个 \(1\) 表示可以在这里结束。
- 需要删掉 \(t\) 的出边。
这样应该是全对了。场上最后这俩我一个都没加/kx
如果要算 \(k\) 次幂显然容易做到 \(O(n^3\min(n,k))\)
C
\(f(l,r)\) 表示删空 \([l,r]\) 的方案数,这里要求每一步都是有效操作,也就是每一步删除至少一个数。转移枚举最后删掉的是 \(a_k\),那么这一步的方案数是 \((a_k-a_{l-1})\);同时删掉 \(a_k\) 之前左右两边独立,于是
最后删掉的是若干段区间,钦定是 \([l_i,r_i]\),其中 \(r_i+1<l_{i+1}\) 也就是相邻两个区间中至少隔一个数,这个直接 DP 就行。具体来说 \(g(i,j)\) 表示 \(a_{1\cdots i}\) 选区间,总长为 \(j\),转移是
有些时候删除可能没用,考虑在序列末尾加 \(q\) 个 \(m\),然后 DP 的时候不算进他们的贡献,即可。
复杂度 \(O((n+q)^3)\)。
决策单调性
四边形不等式优化 - OI Wiki (oi-wiki.org)
两维都有决策单调性。于是可以做到 \(O(n(n+m))\)。当 \(n,m\) 同阶的时候稍微优一些。
2024.2.22
题
对于序列 \(A\),定义 \(f(A,l,r)\) 表示 \(A[l\cdots r]\) 的第一个最大值的出现位置。
定义串 \(A,B\) 等价,当且仅当 \(A,B\) 的每个区间的 \(f\) 都相等。
给定 \(S,T\),问 \(S\) 有多少个长为 \(|T|\) 的子串和 \(T\) 等价。\(1\le |T|\le |S|\le 10^6\)
设 \(p_i\) 为 \(\max\{j|a_j\ge a_i,j<i\}\),则两个串等价当且仅当 \(p\) 相同。
对 \(T\) 建 acam,然后 \(S\) 在上面走。这里走的时候没办法直接像 trie 图那样预处理出边,必须暴力跳 fail。
Mujin Programming Challenge 2017 C
考虑暴力:维护一个栈,每次把当前字符放到栈顶,能消就立刻消掉。
考虑优化:\(f(i)\) 表示最小的 \(j\) 使得 \([i,j)\) 会被消空,\(g(i,c)\) 表示最小的 \(j\) 使得 \([i,j)\) 被消成 \(c\)。
那么
判断区间 \([l,r]\) 能否被消完相当于 \(l\) 开始跳 \(f\),能否恰好跳到 \(r\)。倍增即可。
题
一个字符串 \(s\),\(q\) 次询问一个子串的最短整周期。\(|s|\le 5\times 10^5,q\le 2\times 10^6\)。
recall 一下《2024.1(一) -- UOJ 群》:
给一个长为 \(n\) 的字符串和 \(k\),你需要对其每个长为 \(k\) 的子串算出来其最短整周期的长度。
\(1\le k\le n\le 2\times 10^6\)。
暴力:\(O(n\times d(k))\)。
考虑选一个 \(m\),可以 \(O(n)\) 算出来每个长为 \(k\) 的子串的最短整周期是否为 \(m\) 的约数。于是只需要对每个 \(p^i\mid k\) 都去尝试 check 一下 \(\frac{k}{p^i}\) 这个长度是否为其周期,就可以确定每个位置实际的最短整周期。
复杂度显然不会超过 \(O(n\log n)\)。
本题也是一样的。这相当于逐位确定 \(len\) 的那个约数的每个质因子的指数。
Luogu7035
确定左端点之后,不断右移右端点,发现需要不能超过给定的图案。对每个 \(l\) 找到最远的 \(r\) 使得没有超过,然后算出哈希值比较一下。
题
认为两个串 \(s,t\) 同构当且仅当:对任意的 \(l,r\),\(s[l,r]\) 回文当且仅当 \(t[l,r]\) 回文。
给定字符串 \(s\),问有多少 \(t\) 和 \(s\) 同构。\(1\le |s|\le 10^5\)。
连边建图,连通块缩一下点,要求相邻点颜色不同。
这图不是广义串并联图,那我还会求什么图的染色方案数?recall 一下树上染色,如果我们能钦定一个顺序,使得 \(i\) 加进来的时候,与 \(i\) 相邻的,已经加进来的点之间两两都有连边,那么方案数仍然可以计算。
- 实际上这就是弦图的完美消除序列。
对于本题,可以说明 \(1,2,\cdots,n\) 就是一个合法的顺序。
紧急学习 PAM
把一个串的所有本质不同子串组合成一个结构,回文树上的转移边代表前后同时加一个字符,记作 \(\text{trans}(u,c)\)。这样,可以发现长度奇偶性不同的不会有相互连边,于是我们新建两个根,长度分别为 \(-1,0\),表示奇数长度的本质不同回文子串和偶数长度的本质不同回文子串。
本质不同子串个数是 \(O(n)\) 是好证的,考虑先抽两只宵宫别歪好吗,那么一个 \(i\) 结尾的所有回文子串都满足后一个是前一个的后缀,那既然是后缀对称过去就是一个在前面出现过的回文子串,所以每次新增一个字符,本质不同回文子串个数最多 \(+1\)。
定义 fail link:对于一个节点 \(u\),\(fail(u)\) 指向 \(u\) 代表的字符串的最长回文后缀。(自然也是前缀。)偶根的 fail 指针指向奇根,且只有偶根的 fail link 指向奇根,而我们并不关心奇根的 fail 指针,因为奇根不可能失配。(奇根转移出的下一个状态长度为 \(1\),即单个字符,一定是回文子串。)
例如 \(u=\texttt{abacabacaba}\),则 \(fail(u)\) 指向 \(\texttt{abacaba}\)。
那么我们考虑增量构造,每次往最后加一个字符 \(s_i=c\),尝试找到新增的回文串。这些串自然以 \(i\) 为结尾,那么需要是 \(s[1,i-1]\) 的一个回文后缀,然后前面能拼一个 \(c\)。那么我们不断跳 fail link,直到前一个字符恰好为 \(c\)。你发现这个时候比如说前面 \(c\) 都没出现过,那我们就会一路先跳到偶根,再跳到奇根,然后添加一个 \(c\) 的节点。
这样再走 \(\text{trans}(u,c)\),如果发现没有就新建节点,否则就能知道新的最长回文后缀长度。如果新建了节点 \(v=\text{trans}(u,c)\),还需要知道他的 fail link 指到了哪里。类似地,我们再次不断跳 \(u\) 的 fail link,直到再次遇到一个 \(\text{trans}(u,c)\) 即可。
recall 一下 SAM:每次新增一个字符,我们尝试去添加新的子串,或者分裂新的 endpos 集合。不断从 \(s[1,i]\) 代表的字符串开始跳 parent link,如果存在出边且为连续转移就完事了,否则需要分裂 endpos 集合,并新建节点。如果新建了节点那还需要在原来的那个节点再往上跳,直到存在一个出边,并且需要把一条链上的出边都改掉。
然后你就建出了 PAM。不过比如你要知道这个节点前面的一个字符你还得记录一下他的长度。
把 \(i\to fail(i)\) 连边,可以得到 fail 树。我们每次加一个字符,找到这个最长回文后缀之后,把这个最长回文后缀的权值 \(+1\),那么:
- 一个回文串的出现次数就是 fail 树的子树和。并不难理解,每次我们恰好把该 \(+1\) 的都 \(+1\) 了。
- 类似地,我们不对权值 \(+1\) 而是标记一下出现位置,线段树合并维护 endpos 集合即可得到每个节点的出现位置。
区间本质不同回文子串个数
仍然是先考虑一个串咋做,发现就是 PAM 状态数。
考虑区间询问,考虑一个状态啥时候在这个区间里,设长度为 \(x\),发现需要 endpos 集合里面有一个在 \([l+x-1,r]\) 中的元素。自然应该取 endpos 集合中最大且 \(\le r\) 的元素。离线按 \(r\) 扫描线,维护 \(p_i\) 表示 \(i\) 节点当前的 \(\text{endpos}-\text{len}+1\) 的值,那么每次是链上把 endpos 覆盖成一个数。
发现由于一条 fail link 上面的 len 会形成若干段等差数列,然后如果公差为 \(t\),发现除了最长的串,每个串往左平移 \(t\) 仍然存在,且一定恰好是上一次出现。所以一下就变成了区间加。
再来编一下怎么找这些等差数列:通用的办法是 \(\text{dif}(x)=\text{len}(x)-\text{len}(fail(x))\),然后设 \(\text{slink}(x)\) 为 \(x\) 的祖先中第一个 \(\text{dif}(y)\neq \text{dif}(x)\) 的 \(y\),那么 \(x\) 到 \(y\) 一路上的 \(\text{dif}\) 都一样,并且每次减去 dif 一定恰好等于父亲。
这样我们一个 \(p\) 的贡献原本是给 \([1,\text{endpos}(p)-len(p)+1]\) 这个区间做 \(+1\),现在我的 endpos 加上了 \(t\),我就相当于给一个长为 \(t\) 的区间 \(+1\)。我们发现这个移动的长度恰好等于等差数列的公差,于是这个就变成区间 \(+1\) 了。
注意这里不需要再轻重链剖分了;slink 链剖分本身就满足轻重链剖分的性质:每个点到根只经过 \(O(\log n)\) 条链。
CF932G
注意到一定是把前一段划分一下,后一半就会有对应的划分。
相当于要把 \(s_1s_ns_2s_{n-1}\cdots s_{n/2}s_{n/2+1}\) 划分为若干偶回文串。
\(f_i\) 表示前 \(i\) 个元素的答案,那么 \(f_i=\sum_{j<i}f_j[s[j+1\cdots i] \text{ is Palindrome}]\)。
类似区间本质不同回文子串个数,我们维护 \(g_u\) 表示当前 \(u\) 往上的一条 slink 链上的 \(f_{v-len(v)}\) 的值之和,那么算 \(f\) 只需要把若干个 \(g\) 累加起来。
但是我们还需要更新 \(g\),注意到每次我们实际上只会新增最多一个点,于是可以简单计算。
然后为了保证是偶回文串,需要手动把奇数位置的 dp 数组置为 \(0\)。
我草了,感觉学不明白了啊?开摆了兄弟。省选之后再补
题
给字符串 \(s\),还有一个字符串 \(t\),有 \(q\) 次操作,每次往 \(t\) 前面或者后面加字符,或者给 \(l,r\) 查询 \(t\) 在 \(s[l,r]\) 中的出现次数。\(|s|,q\le 10^5\)
bitset 做法:先对 \(s\) 建 \(26\) 个 bitset,\(F_{c}(j)=[s_j==c]\) 是一个长为 \(|s|\) 的 bitset。
然后维护 \(G_i\) 表示 \(s\) 的以 \(i\) 开头的长为 \(|t|\) 的子串能否匹配 \(t\),那例如我们要在 \(t\) 前面加一个字符 \(x\),就让 \(G_i\leftarrow G_{i+1}\text{ and }F_x(i)\),相当于左移后做一下与;然后如果末尾加字符也容易解决。
或者你直接变成查询 \(s[l,r]\) 中有多少 \(t[p,q]\),然后把 \(s,t\) 拼一起,发现相当于查询有多少个 \(l\le x\le r-(q-p)\),使得 \(lcp(x,p)\le q-p+1\)。离线扫描线即可。
Luogu4218
考虑点分治,枚举分界点 \(1\le i\le M\),需要算出有多少个 \(u\) 满足 \(rt\to u\) 这个字符串是 \(s[i,M]\) 的前缀。每次往末尾加字符。建反串 SAM,需要支持 sam 前面加字符。这也是可以做的,只需要判断新的字符串是否在这个 endpos 集合,以及 len 不超过即可。如果 len 爆了就往 parent 树上儿子跳一步,否则一定是直接走到根。
这样做一次复杂度是 \(O(size+M)\),对 \(size\ge B\) 跑这个,小的跑平方暴力。
那么大的部分复杂度是 \(\sum_{N/2^k\ge B}2^k\times M=O(NM/B)\),小的那部分复杂度是 \(\sum sz^2\),由于 \(sz\le B\),所以就是 \(\sum sz\times B=O(NB)\),取 \(B=\sqrt{M}\) 有复杂度 \(O(N\sqrt{M})\)。
LOJ6806
有一个串 \(s\) 初始为空,你要维护 \(q\) 次操作,支持
- 末尾加字符
- 给定 \(l,r\),设 \(T=s[l\cdots r]\),你需要找到 \(T\) 的最长的一个子串 \(u\),使得 \(u\) 在 \(T\) 中出现至少两次。
\(q\le 10^5\)。强制在线
考虑扫描线,那么强制在线只需要可持久化,然后查询 \(r\) 位置的数据结构。考虑 LCT 维护 sam 结构,每个节点维护 \(p_i\) 表示最小的 \(l\) 使得 \([l,r]\) 中 \(i\) 出现两次,那么每次就是把新增的那些后缀的 \(p\) 改成他们当前的最大 endpos,然后把 endpos 覆盖成 \(r\)。树剖配合颜色段均摊维护连续段,然后还要区间 chkmax 公差为 \(1\) 的等差数列,这些确实都能维护。
这题真魔怔哎呦,场上能有人过?
NOI2018 你的名字
考虑算 \(T\) 有多少个本质不同子串在 \(S\) 中出现过,用总数减掉这个数。
建 \(T\) 的 sam,考虑对每个 \(r\) 算出来最长的 \([l,r]\) 使得 \([l,r]\) 在 \(S\) 中出现过,在 \(S\) 中走 \(T\) 这个字符串,那么如果走不下去了就网上跳 fail link,直到能走下去,这样就可以算出以 \(r\) 结尾的最长长度。由于 sam 的转移边最多让深度 \(+1\),所以这样复杂度均摊没问题。
接下来对 \(T\) 建 sam,然后对每个节点算一下贡献就行了。
计蒜之道
定义字符串 \(S\) 的权值为它的长度除以最小整周期。
给个长度为 \(n\) 的字符串,求有多少对不相交子串,满足它们的权值相同。
\(n\le 10^5\)
先考虑可以相交咋做,设 \(f_k\) 为周期数为 \(k\) 的倍数的子串个数,枚举周期长度 \(L\),那么长度至少为 \(L\) 的子串就需要经过 \(L,2L,\cdots\) 中的至少一个位置。钦定其经过 \(iL\),算 \(iL,(i+1)L\) 往前后最长延伸出多远,那么这个最远区间的所有长为 \(kL\) 的子区间的周期数均为 \(k\) 的倍数。
现在考虑不相交咋做,朴素的想法是钦定 \(i\) 算前缀的方案数和后缀的方案数,然后乘起来。考虑我们相当于有若干次覆盖,\((l,r,k,L)\) 表示区间 \([l,r]\) 的子串,所有长度为 \(kL\) 的串的周期数都是 \(k\) 的倍数,那我按 \(k\) 从大到小考虑,一个串第一次被覆盖就直接确定了它的最大周期数。
咋做啊?
无标号欧拉图计数
欧拉图指的是有至少一条欧拉回路的图。无标号指的是同构算一种。可以有自环,不能重边。
Burnside 引理,拆分成置换环之后边形成若干等价类,每个点对和他相关的等价类有一个约束,最后变成求解 xor 方程组的解数。线性基消元求自由元个数 \(c\),答案就是 \(2^c\)。可以用 bitset 优化。
你发现单次的复杂度甚至是 \(O(\frac{n^4}{w})\) 但是这里的 \(n\) 是置换环个数所以毛估估一下没啥问题
CF1007B
有 \(3!=6\) 种完美匹配,枚举 \(2^6\) 种合法性算容斥系数,对于一种合法性相当于 \(x\in S_1,y\in S_2,z\in S_3\),还要求 \(x\le y\le z\)。注意约数个数不超过 \(128\) 因此暴力即可。
BZOJ4766
答案是 \(n^{m-1}\times m^{n-1}\)
题
给一棵树 \(T_1\),问有多少棵有标号无根树 \(T_2\) 和 \(T_1\) 的边集不交。\(1\le n\le 10^6\)。
容斥钦定某些边必选形成 \(m\) 个连通块,大小分别为 \(a_1,\cdots,a_m\),方案数为 \(n^{m-2}\prod a_i\)。
组合意义变成每个连通块选点然后带容斥系数 DP 即可 \(O(n)\)。
ABC313G
把 \(a\) 排序后钦定一操作用到哪个段内,算一个 floor sum 即可
51nod 算法马拉松 33E
计算 \(\prod_{i=1}^n\sigma_0(i)^{\mu(i)+i}\pmod{10^{12}+39}\)。\(n\le 10^{11}\)
拆成 \(\sigma_0(i)^{\mu(i)}\times \sigma_0(i)^i,\mu\neq 0\) 的部分要算 \(p_1p_2\cdots p_k\le N\) 的个数,也可以 min25。
CF850F
枚举一种颜色,钦定以这种颜色结束,于是变成两种颜色的情况,算期望乘上概率。
SRM 660 DIV1 500pts
考虑每个人来的概率,这只和他往前的一条链(或者环)有关。
连 \(i\to i+1\),考虑如果先来了一个 \(x\),那么 \(x+1\) 就不能来,前后就独立了,于是设 \(f_k\) 表示 \(k\) 个点的链,链尾能来的概率;转移枚举第一个来的人 \(i\),如果 \(i=k\) 则肯定 win 了,\(i=k-1\) 肯定 lose 了,否则 \(i+1\) 不许来,转化为一个长度为 \(k-i-1\) 的链,有
显然可以 \(O(n)\) 算出。对于环,讨论一下发现可以转化为链的情形。
CF113D
相当于有 \(O(n^2)\) 个点,要算出在每个点结束的概率。
可以先高消,算出来右边的系数,然后如果要算在 \(x\) 结束的概率,就只需要把 \(x\) 那一项等于 \(1\) 带进去。这样总复杂度是 \(O(n^6)\)。
实际上可以把状态改成经过 \(i\) 的期望次数,然后就全对了
CF949E
因为 \(2^k,2^k\) 不如 \(2^k,2^{k+1}\),\(2^k,-2^k\) 不如 \(2^{k+1},-2^k\),所以 \(2^k,-2^k\) 最多选一个或者不选。
考虑从低位到高位考虑,考虑 \(2^0\) 选不选,发现如果所有数都是偶数就一定不用选,否则枚举选 \(2^0\) 还是 \(-2^0\),就能把所有奇数都除掉 \(2\),同时去重一下,复杂度就是 \(O(A\log A)\)。
SRM701 900pts
考虑 \(x^ay^b=x^a(n-x)^b\),二项式定理展开出 \(b\) 项,则要算一个 fib 串的 \(x^k\) 之和,直接矩乘优化 dp 即可做到 \(O((a+b)^3\log n)\)。
题
首先给定 \(m\),有 \(Q\) 次询问,每次给 \(n\),问有多少长为 \(n\) 的正整数序列 \(a\) 满足:
- \(a_i\mid m\)
- \(\gcd(a_i,a_{i+1})\neq 1\)
\(2\le n\le 10^9,1\le m\le 10^{16},1\le Q\le 200\)。
朴素的想法是 \(f_{i,S}\) 表示长为 \(i\) 的序列,最后一个数包含质因子的状态为 \(S\);预处理 \(g_S\) 表示质因子集合为 \(S\) 时的方案数,转移就是 \(f_{i,S}\times g_T\to f_{i+1,T}\),其中 \(S\cap T\neq \varnothing\)。
发现 \(S\) 可能会有 \(2^{13}\),但注意到比如 \(m=\prod p_i^{\alpha_i}\),那么 \(\alpha_i\) 相同的 \(p_i\) 本质没有区别,因此可以压掉很多状态。提前预处理转移系数即可。这样状态量不超过 \(w=128\)。
复杂度就是 \(O(w^3\log n+Qw^2\log n)\)。实际上跑 DFA 最小化也可以得到相同的结果。
AGC002E
\(f(i,j)\) 表示删到最小的 \(i\) 个数,进行了 \(j\) 次全局 \(-1\),那么 \(f(i,j)=f(i+1,j+1)\),于是可以直接判断。
CF838C
设 \(x_i\) 为字符 \(i\) 的个数,如果 \(\binom{N}{x_1\ x_2\ \cdots \ x_k}\) 为偶数则先手必胜,否则两人显然都只会删字符,则只和 \(N\) 的奇偶性相关。于是 \(N\) 为奇数时答案 \(k^N\),偶数时要减掉 \(x_1,x_2,\cdots,x_k\) 排列数为偶数的总排列数。
相当于要把 \(N\) 的每一位分到 \(1\cdots k\) 的一个 \(x_i\) 里面,然后算 \(\frac{N!}{\prod x_i!}\) 之和。
考虑 \(f(i,S)\) 表示 \(i\) 种颜色填满 \(S\) 这个集合,转移钦定一个非空集合算进去,子集卷积配合快速幂优化可以做到 \(O(N\log^2N\log K)\)。
注意到 \(k>\text{popcount}(N)\) 时没用,复杂度实际上是 \(O(N\log^2 N\log\log N)\)。
CF1572D
CF1572D - 云浅的小窝 - 洛谷博客 (luogu.com.cn)
UOJ461
把所有 \(O(n^2)\) 个点对排列出来,构成 \(N=\frac{n(n-1)}{2}\) 条边 \(e_1,e_2,\cdots,e_N\)。
二分,找到最大的 \(i\) 使得删掉 \(e_i,e_{i+1},\cdots,e_N\) 时,图是不连通的。那么 \(e_i\) 一定是一条存在的边。
然后保留 \(e_i\),接着找到最大的 \(j<i\) 使得删掉 \(e_j,e_{j+1},\cdots,e_{i-1},e_{i+1},\cdots,e_N\) 时图不连通,这样又能找到一条边。不难发现,这样下去我们会找到图的一棵生成树。
- (实际上就是按我们排出来的这个序下的最小生成树)
这样黑白染色即可确定所有点的颜色;考虑如何判定是否为二分图。这相当于同色点内不能有连边。
考虑我们只保留同色点之间的边以及生成树上的边,每次尝试删除一条生成树上的边,如果图还联通说明同色点之间有边;注意到只要真的有同色边那么取到生成树的那条链上的时候一定能覆盖到,因此这样可以 check 到所有边。
这样询问复杂度是 \((n-1)\log (n^2)+n\) 左右,发现它等于 \(2(n-1)\log n+n\),过不去
那怎么办呢,考虑按 \(n\) 分块,从后往前扫,每次先 check 一下这整个块,如果里面有至少一条边在我们这个 mst 上,就在块内二分,这样每条边代价为 \(\log n\),询问复杂度就是 \((n-1)\log n+2n\)。
P3679
考虑怎么判断 \((S,T)\) 有完美匹配,发现可以 Hall 定理,但这同时和 \(S,T\) 相关。
注意到这等价于 \((S,V_R),(V_L,T)\) 都存在完美匹配(其中 \(V_L,V_R\) 为左右点集),因此 Hall 定理配合 FMT 预处理每个点集是否有完美匹配后两边简单合并即可。复杂度 \(O(n2^n+m2^m)\)。
QOJ6508
考虑朴素的网络流建图,每个让每个点可以匹配两次,发现问题在于可能连出长度 \(\ge 3\) 的链或环。
但注意到,如果连出来一条链或环,对于链一定可以拆成若干 \(2\) 个点的组加一个 \(3\) 个点的组,对于环由于是偶环一定可以拆成匹配,于是孤立点的个数确实几乎最小化了;不过连成环之后不一定最优,因此我们给边加一个费用,每个点的两个容量一个费用为 \(1\),一个费用为 \(M\),求最小费用最大流即可。
模拟赛 16
A
考虑一个 \(f\) 咋算,把逆序对数分为三部分:\(a\to a,S\to S,a\to S\),发现第一部分固定,第三部分可以人为调成 \(0\),并且第二部分一定是把 \(S\) 中的每个数插到贡献最小的位置上。即,\(f_i\) 表示前 \(i\) 个数中 \(>x\) 的数的个数,\(g_i\) 表示后 \(i\) 个数中 \(<x\) 的数的个数,则我们会插入到 \(f_i+g_{i+1}\) 最小的位置上。
还需要证明这个最小值所在的点会随着 \(x\) 增大单调递增,发现每次相当于给 \(f\) 做后缀 \(-1\),给 \(g\) 做前缀 \(+1\),显然这样只会让最小值后移。于是 \(f(a,S)\) 就关于 \(S\) 中的每个位置独立了。
现在考虑原问题,发现 \(p\) 实际上已经确定了 \(b\) 的相对顺序,考虑先对每个 \(i\) 算出来如果已经插入到 \([i,i+1]\) 这里,最优的 \(f+g\) 是多少,记为 \(w_i\)(\(0\le i\le n\))。那么相当于要计数所有的序列 \(x\) 满足 \(x_0+x_1+\cdots+x_{n}=m\) 的 \(\sum w_ix_i+A\) 之和,其中 \(A\) 是原序列逆序对数。
容易发现每个 \(w\) 都是等价的,算出方案数 \(C=\binom{m+n}{n}\),则每个 \(w\) 的系数总和都是 \(C\times \frac{m}{n+1}\)。
于是这题就做完了。复杂度 \(O(n\log n)\)。
B
首先我们把 \(\sum |x_i-y_i|\) 加到答案里。
然后考虑一个 DP:\(f_{i,j}\) 表示前 \(i\) 个位置放了 \(j\) 个点的最小代价。发现钦定完哪些位置放点之后,跨过至少一个点的区间都没有贡献,否则贡献只和两边最近的钦定到的点有关。
我们考虑能否说明最优解一定满足每个选的点都是某个区间的端点。发现两边的代价函数都是凸函数,于是加起来也是上凸函数,越靠近端点肯定就越优。
然后发现代价函数满足四边形不等式,于是就全对了!
那考虑一个 \(w(L,R)\) 怎么算,发现要算所有 \([l_j,r_j]\subseteq [L,R]\) 的 \(\min(l_j-L,R-r_j)\) 之和。
考虑钦定 \(l_j-L>R-r_j\) 也就是 \(l_j+r_j>L+R\),于是我们只关心 \(L+R\) 和 \(l_j+r_j\) 的大小关系,可以简单维护。决策单调性分治一下就是 \(O(nK\log^2n)\)。
C
对于一个串 \(A\) 设 \(p_i=\sum_{j<i}[A_j<A_i]\),则两个串相似当且仅当 \(p\) 相同。
改一下匹配方式,建出 \(B\) 那边 \(p\) 的 acam,那么匹配是容易的!
额代码待补。。。。。。。。。。。。。。。。。。。。
Public Round 12
A
把 \(x\) 排序,相当于要找一个序列 \(y\),满足 \(y_i\ge y_{i-1}+d\),最小化 \(\sum |x_i-y_i|\) 的值。
套路地 slope trick 优化 DP 即可,有一个全局 \(+d\) 的操作可以打标记处理掉。写起来很短。
B
NOIP2023 T3
考虑朴素的 DP,不妨设 \(a_1<b_1\),此时会 ban 掉所有 \(a_i\ge b_j\) 的点 \((i,j)\);每次有三种走法:
- \((i,j)\to (i+1,j)\)
- \((i,j)\to (i,j+1)\)
需要从 \((1,1)\) 走到 \((n,m)\)。
考虑如果 \(\max a\ge \max b\),那么 \(a\) 的最大值那里会直接 ban 一整行,就寄了。
同理如果 \(\min b\le \min a\) 那么也寄了,因此我们希望 \(a,b\) 的 min max 形如
- \(\min a<\min b\le \max a<\max b\)
于是考虑 \(\min a\) 所在的行和 \(\max b\) 所在的列,这一行一列上面的点都是空的,互相都联通。
于是,如果我们能从 \((1,1)\) 走到这一行一列上的某一个点,同时如果这一行一列上存在一个点都可以走到 \((n,m)\),那么就 win 了;否则,由于这一行这一列是 \((1,1)\to (n,m)\) 的必经之路,所以一定寄。
你会特殊性质吗?
发现如果会了特殊性质,那么问题几乎做完了:我们可以把原问题拆成两个具有特殊性质的问题。
考虑这个时候相当于只需要走到最后一行或者最后一列,再考虑 \(a_{1\cdots n-1},b_{1\cdots m-1}\) 的最大值,发现这个时候只 ban 一行或者一列的话,不一定寄了,有可能我们在之前就走到最后一列了,但总之可以缩减一下问题;如果同时 ban 了一行一列,那还是会寄。
那这样就做完了啊,复杂度 \(O(qn)\)。具体来说我们维护一下当前这条折线上下边界和右边界是否被堵住就好了。
湖北省选模拟 Day1
A
相当于每条边有一个开始区间 \([L,R]\) 和结束区间 \([O,C]\),每次需要从 \([L_i,R_i]\to [O_j,C_j]\),要求 \(O_j\le L_i\le R_i\le C_j\),而且要求最后走过的那条边的 \(R\) 最小。
注意到 \(O,L\le 20\),优化一下建图跑 BFS 求出每条边是否可达就行了。
总时间复杂度是 \(O(M\log M+L(N+M))\),log 来自排序
B
注意到一个集合 \(S\) 中两两 xor 的 min 一定在相邻值处取到,因此容易设计 DP:先把 \(a\) 排序,然后设 \(f(i,j,0/1)\) 表示前 \(i\) 个数,\(i\) 在 \(S_0/S_1\) 中,上一个在不同集合中的数为 \(j\),转移就讨论一下新的数在哪个集合中,有
- \(f(i,j,c)\to f(i+1,j,c)\),要求 \(a_i\oplus a_{i+1}\ge k_c\)
- \(f(i,j,c)\to f(i+1,a_i,1-c)\),要求 \(a_{i+1}\oplus j\ge k_{1-c}\)
发现每次是继承所有 \(f\) 的值(或者全局清空),然后再做一个单点修改。
01trie 维护整体 DP 转移即可,复杂度 \(O(n\log V)\)。
C
注意到路径可以重复走,首先线段树分治判一下是否联通,接下来考虑怎么构造解。
注意到连通块大小 \(\ge 2\),因此对每个相邻的数字对 \((p,q)\) 我们都可以走过去再走回来,从而让 \(v\leftarrow 100v+10q+p\)。
感觉只有 \(O(1)\) 种情况需要判断,唯一需要写的是线段树分治维护连通性?没时间写了啊,摆
QOJ7401
我们认为两个串 \(s,t\) 等价,当且仅当它们可以通过这些操作互相到达。那么可以证明,所有串都会被划分到 \(24\) 个等价类中。进一步,这 \(24\) 个等价类构成了一个群,运算是字符串的拼接,\(s\) 的逆元定义为字符串 \(t\) 使得 \(s+t\) 等价于空串。
为了找到这些拼接关系,我们可以爆搜长度较小的串,这样就能找到所有等价类以及运算表。
得到拼接关系之后我们就能知道 \(0,1,2\) 三种字符各自所在的等价类,于是判断一个串在哪个等价类中就可以直接一个一个加过去;对于本题,注意到只有 \(24\) 种等价类,因此可以 \(O(nC)\) 地统计每个等价类中的子串个数,其中 \(C=24\)。具体地,枚举 \(r\),然后乘上 \(s_{1\cdots l-1}\) 所在等价类的逆就能知道 \(s[l\cdots r]\) 所在的等价类;只需要知道每种等价类的前缀个数即可。于是有复杂度 \(O(nC+m)\)。
另一个题是给若干操作,问给定的串 \(S\) 能到达多少长为 \(n\) 的串。我们考虑在自动机上 DP,相当于最后要走到 \(S\) 所在的等价类,于是容易做到 \(O(nC+|S|)\) 或 \(O(C^3\log n+|S|)\)。
湖北省选模拟 Day2
A
相当于问有多少种本质不同的操作序列。
设 \(f(l,r,k)\) 表示区间 \([l,r]\) 用 \(k\) 次操作删完的方案数,转移考虑最后一次删的颜色 \(c\),那么相当于有一些这个颜色的位置,把区间划分成若干段,段之间互相独立,需要把每段的 egf 卷起来。
于是再设 \(g(l,r,k,c)\) 表示区间 \([l,r]\) 用了 \(k\) 次操作,删到只剩颜色 \(c\),且至少剩下一个颜色 \(c\) 的方案数。那么
考虑 \(g\),转移枚举最后一个被保留的位置 \(p\),要求 \(a_p=c\),转移到
复杂度是 \(O(n^5)\),写个记搜只要跑 0.1s。注意一个 \(g(l,r,k,c)\) 对所有 \(c\),\(p\) 那一维的枚举量总共是 \(r-l+1\),因此总复杂度为 \(O(n^5)\) 而非 \(O(n^6)\)。
B
这个题给的是点仙人掌,还算有点良心!!
考虑一个点被包含的概率,发现相当于到他的路径上有若干个环,每个环都得被打通。考虑一个环被打通的概率,设左右两条链概率乘积分别为 \(L,R\),那么概率就是 \(L+R-L\times R\)。然后还有最后他所在的环有个概率,也是这样的形式。然后一个环对于不同的入点和出点会有不同的 \(L,R\)。
先把仙人掌的环缩掉,此时变成对于一条钦定的路径,每个点有一个打通的概率,这与它前后具体是哪条边有关。然后需要对每个 \(i\) 算 \(\sum_j P_{i\to j}\)。
我们来仔细写一下这个概率,把一个环上的点拿出来看,从一个点 \(u\) 处断开为链,设 \(p_i\) 为 \(u\to i\) 链上的概率乘积,\(q_i\) 表示 \(i\to u\) 链上的概率乘积 ,\(M\) 表示所有边的概率乘积,那么如果进来的点是 \(i\),出去的点是 \(j\) 的话,当 \(i<j\) 的时候为 \(p_iq_j+\frac{M}{p_iq_j}-M\),否则就反过来。
那我们 DP,首先算出来 \(g_u\) 表示,如果从 \(u\) 开始走,限制不许走出环,它的概率的乘积之和。那么这个就是
预处理前后缀 \(\sum p,\frac{1}{p},q,\frac{1}{q}\) 即可。
然后设 \(f_u\) 表示 \(u\) 这个环,往下走的概率乘积之和。这里认为 \(u\) 这个环取的概率一定是它父亲到它的那条边为入边,然后出边就是往下走的那条边。设 \(s(u)\) 为 \(u\) 父亲连到他的那个点,那么转移是
其中 \(\text{Pr}(x\to y\to z)\) 表示如果我们前一个点是 \(x\),后一个点是 \(z\),经过 \(y\) 的时候,\(y\) 的概率。
\(w(u,v)\) 表示一条边 \((u,v)\) 存在的概率。
然后我们还要换根。先删掉一个子树,把 \(g\) 改一下就行。
真难写......不写了,原神启动耶耶耶
正则二分图完美匹配
- 对于左右各 \(n\) 个点的 \(k\) 正则二分图,存在算法在 \(O(n\log n+nk)\) 的时间内求出其完美匹配。
\(k=2^d\)
当 \(d=0\) 时,直接把 \(n\) 条边输出即可。
当 \(d\ge 1\) 时,跑欧拉回路后给每条边定向,这样每个点都有 \(2^{d-1}\) 条入边和出边,于是直接删掉右部点的出边(它们也是左部点的入边),就得到了一个 \(2^{d-1}\) 条边的正则二分图。
该算法的时间复杂度是 \((2^d+2^{d-1}+\cdots+1)\times n=O(nk)\),也就是边数级别,到达理论下界。
\(k\) 任意时
考虑每次随机一个左边的未匹配点,然后随机选一条增广路。具体来说我们从左边开始走,往右的时候随机走非匹配边,往左的时候随机走匹配边。
这样,第 \(i\) 轮算法走出的增广路长度为期望 \(O(\frac{n}{n-i})\),故总复杂度为期望 \(O(n\log n)\)。
实现的时候可以把左部点 random_shuffle
,然后依次匹配。
题
给 \(a,b,c,n\),求
\[\max_{i=0}^n((ai+b)\bmod c) \]\(1\le a,b,c,n\le 10^{18}\)。
- \(O(\log^2n)\):二分答案 mid,有
类欧计算。
- \(O(\log n)\):直接类欧,把 min max 都设出来。
LOJ3701
钦定最小值 \(=x\),则最大值 \(\le x+K\)。改成算
现在考虑一个 \(\min\ge x,\max \le x+K\) 的答案怎么算。发现相当于对每个 \([l,r]\) 向 \([x,x+K]\) 取交,然后选一条链把所有 \(r-l+1\) 乘起来;对于第二问考虑钦定一个 \(i\) 算贡献,也有类似的形式。
考虑每个 \([l,r]\) 对于不同的 \(x\) 会形成至多五段分段函数,每段都是一个一次式。设 \(P_{i,j}(x)\) 表示 \(i\to j\) 链上钦定 \(\min\ge x,\max \le x+K\) 时的答案,则 \(P_{i,j}\) 是一个分成至多 \(5n\) 段的分段函数,每段都是一个不超过 \(n\) 次的多项式。我们要算的是 \(\sum_{x=1}^V\sum_{i,j}P_{i,j}(x)\)。
枚举 \(x\) 所在的段,虽然其实可以直接维护这个多项式但我懒了,考虑 \(Q_{i,j}(x)=\sum_{y=1}^xP_{i,j}(x)\) 是一个至多 \(n+1\) 次的分段函数,考虑先算 \(n+2\) 个点值(这里算点值还不能暴力,需要 \(O(n)\) 换根 dp 一手才能保证复杂度),然后插值即可。复杂度是 \(O(n^3)\)。
再考虑第二问,发现需要枚举一个 \(i\),算出所有包含他但是不计算他的贡献的方案数多项式 \(R_i(x)\),然后算 \(R_i(x)\times \sum_{l_i\le y\le r_i}y\)。发现 \(R_i\) 是不超过 \(n\) 次的多项式,那么 \(R_i(x)\times \sum y\) 是不超过 \(n+2\) 次的多项式,再对 \(y\) 求和就不超过 \(n+3\) 次。于是只需要算 \(n+4\) 个点值。
然后这个比较卡常,要来一个重心拉插
重心拉格朗日插值法:设取的点值满足 \(x_i=i+A\),要求 \(k\) 处点值,则有:
\[F(k)=\sum_{i=1}^{n}y_i\prod_{j\neq i}\frac{k-(j+A)}{i-j} \]可以发现分母就是 \((i-1)!\times (n-i)!\),分子可以预处理 \(\prod_{j}(k-(j+A))\) 的前后缀乘积 \(O(1)\) 计算,因此可以在 \(O(n)\) 时间内算一个点值。
综上,总复杂度 \(O(n^3)\)。