一些题解

1.贴贴

懒得写代码了

首先有个单次询问O(n)的直接换根DP做法,枚举相遇点,略。

像这种每次找一类点计算答案的题,考虑虚树。

有个结论:相遇点选在颜色为x或y的点上 不会更劣

所以只需要在同时包含x和y色的虚树上换根DP,枚举相遇点就行了

但复杂度波动很大。当max(size x,size y)比较大时,复杂度就高;

考虑均衡一下,根号分治。maxsize<sqrtn直接暴力,预处理所有maxsize>sqrtn的对,O(n sqrt n)。(具体来说,对于每个size>sqrtn的点,在原树上换根DP。在颜色为k的点上时,就和k的虚树统计答案)

还有个小优化,每次建同时包含x色和y色的虚树时,不用按dfs重新排序,只需要把x色和y色的有序序列归并一下,这样子每次直接算答案的部分,复杂度就优化到了O(sqrt n)

O(nsqrtn+msqrtn)

2.The Tree

有几个巨佬,非常快的秒掉了。

我当时想了个定期重构的方法,但是没写。

首先感操作1不好操作,查询很好操作。考虑平衡一下,操作1直接考虑在x点打标记 w++,查询就查x到根的链。

查询时,x点为黑,当且仅当存在x的一个父亲y,满足x到y路径所经过的点数 小于路径上所有点的w之和。

初始时把每个w设置成-1,就相当于判断 x到根的路径 的所有后缀路径 的w之和 的最大值 ,是否>=0。

考虑树剖加线段树维护。

至于操作2,先把x的子树的点赋值为-1(我到现在才意识到 树剖是可以子树修改,子树查询的),再考虑减去x的祖先对子树的贡献。

如果x的祖先y影响到了x的子树,一定会向下蔓延(x到y路径的w之和)层。我们就把x的w减去(x到y路径的w之和)+1,类似于用海绵吸掉蔓延的黑色

但是假设我算答案的时候,没有取到y,但经过了x,x就会吸掉无辜的黑色,会不会有问题呢?

实际不会,显然取x一定不如取y优秀,毕竟(x到y路径的w之和)>=0,除非……有其他操作2。但是一对x到y的路径上的点 进行操作2,x的w就成-1了,也不会吸了。

时间复杂度O(nlog^2)

3.Beautiful League 昆特牌

sto nkrqoi002

首先做这道题,要会有向完全图三元环计数。

手玩一下可以发现,三元环不太好计数,但是非三元环很好计数。对于任意三个点,只要有一个点有两个入度,这就是个非三元环。

(确定三元环需要三个点的状态,而确定非三元只需要一个点的状态)

因此 可以容斥。三元环总个数就是C n3 -∑C in[u] 2,每个三元环只会被计算一次。

得出这个美丽的式子之后,考虑如何计算答案,首先C n3是定值,对答案无影响,只剩 -∑in[u]*(in[u]-1)/2,除以2也可以提,就变成了∑in[u]-∑in[u]^2

∑in[u]值是定值 我们只用让∑in[u]^2最小。

这种选择性定向的题,比较容易想到网络流。选择费用流,s连询问点,询问点连右边原图上的点,原图上的点就1,3,5,7地往t连。

4.平均回文

枚举中心+二分哈希

每次两边同时遇到一个‘?’,概率就要除以26。多除几个26,概率就爆出精度了,直接结束循环。挺有意思

5.小w的喜糖

这题在容斥专题里,所以是容斥(而且约束条件有点怪。

F[i]表示至少有i个人与手中糖的颜色冲突 的方案数。我们只需要固定i个人冲突,其他人随便选,就可以计算f[i]。f[i]容斥一下就是最终答案了!

我们现在只需要研究固定i人冲突的方案数了

由于原题的同一颜色糖果等价,不太好处理,有一个小技巧,先把每颗糖都当做不同的,只考虑约束条件,最后求出方案数后,再按可重集排列去重(学到了!!!)。

我们考虑在每种颜色中选一些人来冲突,这不太好直接列式子,数据范围又小,直接dp。

dp[i][j]表示前i种颜色,已经选了j个冲突的人,的总方案数

转移明显就是枚举当前选几人冲突,dp[i][j]=∑C(num[i],k)*A(num[i],k)*dp[i-1][j-k] ,注意我们已经假设每颗糖不同,所以要乘A()

F[i]=f[n][i]*(n-i)!   最后容斥一下即可得到答案(别忘了去重)

6.[省选联考 2020 A 卷] 树

看到zmz再看这道题,我就凑上去看了看,并点开了算法标签,说“太简单了,这不就是,倍增 加 trie树 加 位运算吗,秒了!”

后来我想了一下这道题,发现按trie树一想就直接出来了,trie树合并 加一个 搜11111链并交换节点左右儿子的修改,O(nlogn),看了一眼题解,可以这么写。

(之前希希好像口胡了一道题让我想,解法就是交换线段树的左右儿子,导致想这道题简单了许多)

当初不该看标签,感觉略过了这题最难的部分。

收获:trie树可以合并,+1操作可以在trie树上体现

7.https://www.luogu.com.cn/problem/P5445

这道题在CDQ作业表里,当时就一直对着CDQ想,始终想不出来,对时间分治,区间分治好像都不行,便“低头”了。

实际上是需要转化的。因为我低头了,所以我不太清楚咋想到转化,因为我真的想不到啊。

洛谷一篇blog写道:"看到点对,什么思路?转化为平面问题。显然点对连通性可以转化到平面上”

挺有道理,这种二元组,点对的题,都可能联系上矩阵(学到了!!)

 

总之,可以使用一个矩阵表示连通性。当联通 i-1 所在的连通块(L)和 i+1所在的连通块(R)时,给每个(l,r)和(r,l)加上q-now的值。

相对的,当删除时,给每个(l,r)和(r,l)减去q-now的值。

发现这玩意是个矩阵操作,要求矩阵加,矩阵减,单点求值。

二维线段树和CDQ都能过(实际上我一种都没写,口胡)

8.I - [WF2015 J] Tile Cutting | CQNK (nks.edu.cn)

很骚的一道题。

首先一眼感觉这玩意和询问没多大关系,应该是诈骗。我们直接不管,尝试求出每个cnt[size]

初感觉就是在矩形(或直角梯形)的基础上,加上一些变量,来唯一地确定一个平行四边形,并表示出它的面积(毕竟你看题面给你的图片,都是一个矩形框住了一个平行四边形),再从其面积的式子中找点规律。

然后我们随便设设,like this


(很悲伤的是,在开这道题的时候,我还挺快地想出了以上步骤,结果我把平四面积表示错了!表示成了个6项式,直接舍弃了这种做法)

 我们就会发现这玩意的面积为ad+bc!!!简直是送到嘴上的FFT (也没有很送到嘴上,因为它在FFT专题里)( Ci=∑Ai-j*Bj,这个平行四边形面积就是 i ,ad 就是 i-j,bc 就是 j)

然后就可以很舒服的用FFT搞了

最后询问随便处理处理就行,我写的st表。

M - [Tjoi2016&Heoi2016]求和 | CQNK

another 多项式乘法

首先我们直接把第二类斯特林数拆开,再约一下分,可得

 理性分析一波。右边的一坨中,分别有和 j ,j-k ,k ,(k和i)相关的项,

我们发现 j ,j-k ,k 这种处理着很舒服,只有n种值,看着就像多项式乘法 ;与 k 和 i 同时相关的项就很难受,它有n*n数量级的取值,不好搞。

但是与 i 相关的只有 k^i 这一项,我们可以考虑把 sigma i拿进去。

 

我们发现几乎搞了个寂寞,g数组也求不了,而且式子里又多了一个与 j 和 k 同时相关的项。

当时到这里就做不动了。

然后请教了一下柏霖,他说 “把 j 的上界换成 n”。我听了一脸懵,又看了一眼原式子,恍然大悟。

首先把 j > i 时肯定不影响答案

注意到如果把 j 的上界换成 n,i 与 j 就无关了。再来看 k^i ,惊讶地发现,原本需要传入 j k的 g() 只需要传入一个 k 了!!!因为 i 不再受 j 的约束了!!!

现在式子里只有和 j ,j-k ,k 相关的项,NTT O(n*logn) 解决!

这种思路可以用来去除变量间的约束,挺有用的。

G - 小 G 的布料 | CQNK

你一看枚举矩形,要么枚举右下角,要么扫描线。

枚举右下角试了试,发现不太好维护某些东西;又试了试扫描线,发现有一个 ∑minn(l,r)+1-( K/len ) 的式子。枚举 l,r 显然是不行的,那就枚举值。

K/len像是可以整除分块,但是minn(l,r)就难搞了。于是咱们就搞 minn(l,r)。笛卡尔树呼之欲出,式子成了∑(minn+1-( K/len ))*sumlen,拆成∑(minn+1)*sumlen-∑( K/len )*sumlen 

sumlen实际上是一个先增再不变后减函数,增减量都为+-1,∑(minn+1)*sumlen 等差数列,∑( K/len )*sumlen 预处理

 场上1h想出来,1.5h都没写出来!!!

最后开始赌博,孤注一掷,发现没戏,速码暴力,暴力还CE了,光荣爆零。

P - 金轮法王的龙象般若功却被老师逮个正着 | CQNK

哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈!!!

终于有一道纯自己过的题了

而且做法挺优秀(!!!

但是这道题还想了比较久,昨天想了1h,写了1h,调了1h。

首先很明显枚举最大的惩罚系数,再求所有方案人数之和。对第 i 人,右边随便选,左边确保其交集为空

先来个 Ei,表示有 i 个元素,选出若干子集使得它们交集为空

二项式反演容斥一下可得)

再来个 Fi,表示有 i 个元素,所有选子集方案中,选出子集交集大小之和

 然后自以为可以统计答案了,随便写了个啥式子,发现过不了样例,调了一晚上后,我发现我的式子萎了。

大概就是我默认把 i 左边的人全部不选。没考虑到 i 左边的人也可以被选在其中一些集合中,只要不被包含再交集中就行了。

于是乎我又列了一个式子

Gi 表示 n 个人中,(前 i 个人交集为0,第 i+1 人必选,其他人随意选) 的 所有选子集方案中,选出子集交集大小之和

 (再次二项式反演容斥)

以上三式皆可用NTT算,这个肯定就没问题了。

按照正常剧情,现在我就应该A了,但是NKOJ为这段故事填上了浓墨重彩的一笔

意思就是被卡常了。

问了一下他们,他们说他们只用了两次多项式乘法,而且还要强制 limit 为 2*n 而不是 4*n。

我尝试把上面的式子合并,发现不行。

当我拎出其中一个式子时,我发现我就是个 傻B

"再来个 Fi,表示有 i 个元素,所有选子集方案中,选出子集交集大小之和"

加入这玩意强迫你O(1)求 Fi ,咋求?

咱直接讨论 每个元素 j 有多少贡献。只有当选出所有子集都包含 j 时 它才有贡献,这不就是

 

选出的每个集合都必须包含 j ,一共 2^(i-1) 个这种集合,总方案就是2^2^(i-1)-1(空集),每个元素又等价所以*i

过了

 

这个故事告诉我们,别学NTT学傻了(我觉得我思路也有点奇怪,正常应该先想到G的式子,再想到F的式子,鉴定为学多项式学的

N - 「HAOI2018」染色 | CQNK

很明显直接枚举  N个位置中出现次数恰好为S的颜色种数

尝试统计 N个位置中出现次数恰好为S的颜色种数为i 的方案数。发现不太好搞,考虑 N个位置中出现次数至少为S的颜色种数为i 的方案数

假设有 i 种颜色,首先有一个C(m,i),iS 个位置类似可重集排列,剩下位置的随便在(n-i)选。

但这样子还是会算重方案数,具体式子我忘了(应该长得和下图形式二差不多)。

反正得二项式反演一下。

然后就可以NTT了

d - 迫真大游戏 | CQNK

论文题,学到了一些推式子思路。

根据经验,我们考虑只算出环长为 i 时第一个人的存活率,其他人的存活率就可以直接表示

设一个人死的概率为p,活的概率为q=(1-p),很容易推出一个人在前i轮死掉的概率为1-q^i;然后又可以推出 n-1人在前 i 轮全死的概率为(1-q^i)^n。

然后就可以列式子,设当前环长为n,第一个人最后死,当且仅当他在第 i 轮结束的新一轮后死掉时,剩下n-1人在i轮之内全死了。

可以列式

 (不会latex)

然后F也可以用多项式乘法算了

这个推式子对我来说挺有启发性,建议反复观摩

ⓒ - [20231115]子集计数 | CQNK

4个月前场切了,今天看了1h之前的代码才看懂是怎么写的

首先我们可以想到一些暴力,比如O(1)修改, O(n)枚举子集查询;或者O(n)枚举超集修改,O(1)查询。但是都过不了

看到这修改和查询用时的不平衡,我们可以想到结合一下。

正常做法:

把一个数拆成两部分,前一半位和后一半位。然后设 f s1 s2为前一半位恰好为 s1,后一半位为 s2 的子集,的总方案数。

这样子查询就只需要枚 s1 的子集,修改就只需要枚举 s2 的超集,成功平均。

我当时的离谱做法:

把数分为 bitcount>=8(A类) 和 <8(B类) 两种

算贡献时:(当前计算的是 => 号右边的贡献)

A对A的贡献:超集修改,单点查询

B对B的贡献:单点修改,子集查询

A对B的贡献:推一下发现,A对B有贡献当且仅当 A的补集&B=0。

又有一个很神奇的性质,如果对B子集修改,对A的补集的子集查询时 对 popcount%2 进行(+-)容斥,只有当 A的补集&B=0 时,B的贡献才不会被容斥抵消

(我也不知道我当年是怎么想到的)

按照上面实现即可。

K - 序列 | CQNK

我是傻逼我是傻逼哦我是傻逼我是傻逼我是的我怕调查的2发如此肤浅如果vi哦1其他人突然发。 vbqwrtbn

有一个性质,当且仅当m在二进制下是n的子集时, C(n,m)为奇数。手玩和用拓展卢卡斯均可得到。(这是之前一道题的结论)

然后就变成了上面那道题倒过来。

如果偏要正着做,我当时的离谱做法好像就不太好推了;但是正常做法依然强劲。

所以说这题等于两道原题加起来

L - 欧拉 | CQNK

考场上执着于莫队,导致一直没想出正解。

实际上区间查询的题不只有莫队一种较通用的做法。

可以用数据结构,整体二分,莫队,对询问按右端点排序再挪指针 等等。

对于(是否存在某个元素)这种问题,莫队 和 排序加挪指针 比较常见。

这道题就是最后那种。

我们只需要在挪动右端点的同时,维护 当前倒数第一个 a[i] 含有某个质因子p的 i ,在树状数组中 标记一下它的贡献(p-1)/p 。O(nlogn^2)

Problem - 553E - Codeforces

感觉比较板的一题,估计是因为分治FFT本身就是紫题了。

很明显,这是一道概率DP,我们得先设状态 F u i ,表示当前是第 i 秒,在 u 点,到n点的最小期望。

如果将 F u 作为一个整体去转移,就会发现转移中有环。于是不得不枚举 i ,一层一层地转移

\(F_{u,i}=min_v\{\sum_{j=1}^tF_{v,j}*P(uv,j-i)\}\)

就可以O(n*t^2)地求解了。

尝试发现一些性质,最后你会发现没有性质。

首先这题似乎不太符合普通最短路的性质,有可能走回头路,比如

 再猜点其他结论,什么通过某个点一条边转移的时间点是连续的,等等,会发现都不成立。

我们就把矛头指向DP方程

\(F_{u,i}=min_v\{\sum_{j=1}^tF_{v,j}*P(uv,j-i)\}\)

然后就会发现这玩意是一个卷积的形式,又结合一层一层转移的特点,我们可以使用分治FFT求解

具体的,对于每一条边建立多项式,求 $min_v\{\sum_{j=1}^tF_{v,j}*P(uv,j-i)\}$ 即可

 

P5437 【XR-2】约定 - 洛谷

首先我们把总期望转化为每条边的期望之和,明显每条边被选中的概率相同,都是 \(\frac{n-1}{\frac{n*(n-1)}2}\) ,即 \(\frac2n\)

(这个可以由 \(\frac{C_S^{n-1}}{C_{S-1}^{n-2}}\) 化开得到,其中 \(S=\frac{n*(n-1)}2\);也可以理解为每条边的期望是 \(1\),最后所有边的期望之和为 \(n-1\)

\( \begin{aligned} F(n)&amp;=\sum_{i=1}^n\sum_{j=i+1}^n(i+j)^m\\ &amp;=\sum_{i=1}^n\sum_{j=2*i+1}^{i+n}j^m\\ &amp;=\sum_{i=1}^nS(i+n)-S(2*i)\\ &amp;=\sum_{i=1}^nS(i+n)-\sum_{i=1}^nS(2*i) \end{aligned} \)

拉格朗日插一下\(F(n)\)即可

最后别忘乘 \(\frac2n\)

Ⓑ - 【SAM】子串的价值

很琴瑟的一道题

首先,子串长度*出现次数 = 后缀自动机

所有直接上SAM!!!\(O(n)\)

对于第一问,由于我们无法一次存下所有价值,所以只能二分答案ans(这玩意明显有单调性),然后判断价值>=ans 的子串有没有m个(这部分在自动机上做,\(O(n)\)),一共 \(O(n*logn)\)

二分出ans后,直接把 价值>=ans 的子串的价值 全部取出来排序即可,\(O(n*logn)\)

(这里有一个小问题,如何保证价值>=ans 的子串的数量?首先价值>ans的子串的数量不超过m;其次价值=ans 的子串的数量也是 \(O(n)\) 级别:对于自动机上每个点所表示的子串,至多只有一个价值=ans)(或者你也可以直接把 价值>ans 的子串的价值 取出来排序,剩下的全用ans补上)

对于第二问,我们采用与第一问相似的思想:先二分答案算出第k小的子串的价值ans,再让 k-=(价值小于ans的子串数量)最后对 价值=ans的子串 ,找出第k小。

一种方法是排序,使用哈希,存子串只需要存它在原串中的pos,根据上面的证明,这是 \(O(n*log^2n)\)的;这道题又只需要求第k大,所以可以使用nth_element,\(O(n*logn)\)

当然还有更优秀的方法:

我们充分利用fail树的性质:每个节点所代表的子串 是 其子树内所有节点所代表的子串 的后缀

那我们 reverse 一下再建树,则,每个节点所代表的子串 是 其子树内所有节点所代表的子串 的前缀

说明每个节点所代表的子串 比 其子树内所有节点所代表的子串 字典序小。

那我们就可以预处理子树内 价值=ans的子串 个数和,最后按字典序在fail树上随便跑跑就完了

(另一个小问题,要想在fail树上从上往下跑,我们需要把它改造成 类trie树,如图)

 

(边权为,son代表子串的从后往前数的第len[father]+1个字符)

(具体怎么存子串?还是存 其在原串上的pos)

总结:其实这道题并不难想,二分答案之类的呼之欲出。只不过是想介绍一下存pos,fail树转trie树之类的思想。可以说是为了这盘醋包了顿饺子。

posted @ 2024-02-19 19:07  zhuzc_114514  阅读(12)  评论(0编辑  收藏  举报