2024.05 做题笔记

P6617

由于 \(w\) 是固定的,容易想到去维护前驱。具体而言,对于每个 \(i\),维护 \(i\) 之前第一个 \(w-a_i\),这样可以解决不带修的部分分。

发现带修就寄了!因为一次可能修改 \(\mathcal O(n)\) 个位置的前驱。但是考虑到我们只需要判断是否存在,因此如果 \(a_i\) 前的第一个 \(w-a_i\)\(a_j\),且 \(j,i\) 之间有 \(a_i\),那么 \((j,i)\) 这个 pair 显然不优。我们只需要维护所有支配点对,这时候每次修改只会影响 \(\mathcal O(1)\) 个位置,用线段树 + set 维护,时间复杂度 \(\mathcal O(n\log n)\)

P5179

神秘题。

容易证明最小化分母等价于最小化分子。

\(\frac{a}{b}<1<\frac{c}{d}\) 时肯定取 \(\frac{1}{1}\),当两个数有共同整数部分的时候可以扣除,这时候 \(\frac{a}{b},\frac{c}{d}<1\)。我们考虑翻转,即求 \(\frac{d}{c}<\frac{v}{u}<\frac{b}{a}\),继续递归即可,复杂度同欧几里得 gcd,为 \(\mathcal O(\log n)\)

P6060

观察到 \(D(n^k)\) 是关于 \(k\)\(\omega(n)\) 次多项式。求出多项式的前缀和,每次询问直接代入求值即可。复杂度 \(\mathcal O(n\omega(n)+T\omega(n))\)

P7526

首先考虑抽象成集合幂级数。相当于现在有 \(n\) 个集合幂级数 \(F_{i}(x)=x^{a_i}\),我们需要从中选出 \(m\) 个,求他们的异或卷积的和。

那么第一步容易想到做 FWT,我们要求从 \(n\) 个 FWT 后的结果中选出 \(m\) 个,他们的乘积的 IFWT 的结果的和。

FWT 和 IFWT 是具有线性性的,也就是说:\(\operatorname{FWT}(a)+\operatorname{FWT}(b)=\operatorname{FWT}(a+b)\),也就是说我们只要求出所有 FWT 后的集合幂级数中选出 \(m\) 个的乘积之和,最后整体做一遍 IFWT 即可。

考虑一下对单项式做异或 FWT 的结果:\(x^{a_i}\) 在 FWT 后每位都是 \(1\)\(-1\)。那么这时候一个经典的 trick 就是你考虑求出每一位的 FWT 结果之和,就能解一个方程得到每一位上有多少 \(-1\)\(1\)。因此你考虑把所有 \(x^{a_i}\) 求和,做一遍 FWT,这样你就能求出每位的 \(-1\)\(1\) 的数量。

接下来考虑每位选出 \(m\) 个数的乘积之和。假设这位有 \(c\)\(-1\),那么这位的结果为:

\[\sum\limits_{i=0}^{c}(-1)^{i}\binom{c}{i}\binom{n-c}{m-i} \]

展开后容易发现是一个卷积的形式,可以用 NTT 做到 \(\mathcal O(n\log n+2^ww)\),获得尊贵的 98 分!

最后 2 分比较生气!发现上面这个东西是关于 \(c\) 的至多 \(m+1\) 次多项式,因此我们可以用 98 分的做法求出 \([0,m]\) 的点值,进行一次快速插值求得这个多项式,最后再用一次多点求值求出 \(2^w\) 个要用的点值。时间复杂度 \(\mathcal O(m\log^2 m+2^ww^2)\),实现的比较好就可以获得 100 分!(上面的卷积需要改一下,因为我们不好算 \((n-c)!\),可以转成下降幂处理。)

我的代码只有 10KB,可以说是相当得好写了!

ABC313G

所有的结局序列一定可以通过先做若干次全局 \(-1\),再做若干次全局 \(+1\) 得到。那么我们将原序列进行排序,枚举最终消到了哪个 \(a_i\),最后求和形如 \(\sum\limits_{i=1}^{n}\lfloor\frac{ai+b}{c}\rfloor\),直接万能欧几里得即可。

AGC003D

如果质因数分解完成了,问题容易解决:只需要将每个质因子的次幂对 \(3\) 取模,那么每个数都有一个对应的不能选的数,用一个 map 统计即可,需要特判完全立方数不能同时选。如果用 Pollard-Rho 可以做到 \(\mathcal O(nV^{\frac{1}{4}}+n\log n)\)

但是 PR 有点麻烦。我们考虑三次根号分治,对于 \(\le V^{\frac{1}{3}}\) 的质因子,直接暴力筛出来,剩下的只可能形如 \(1,p,p^2,pq\)\(p,q\) 为质数),只需要判断这个剩下的部分是不是完全平方即可,因为无论是 \(p\) 还是 \(pq\) 都只需要乘上剩余部分的平方。时间复杂度 \(\mathcal O(n\pi(V^{1}{3})+n\log n)\)

ABC240Ex

考虑一组合法的解长成什么样。观察相邻的串的长度,如果上一个选的长度为 \(l\),那么下一个选的长度不可能超过 \(l+1\)(如果超过 \(l+1\),那么把最后一个字符截掉肯定不劣),因此所有串长不超过 \(\mathcal O(\sqrt n)\)。直接全部插入 trie 树,按照 trie 树的顺序做二维偏序即可。时间复杂度 \(\mathcal O(n\sqrt n\log n)\)

ABC240F

枚举整段的取到了哪里,设为 \(i\)。那么考虑 \(i+1\) 段内部的贡献,设前 \(i\) 段前缀和为 \(s\),那么选出 \(c\) 个会贡献 \(s+\frac{c(c+1)}{2}x_{i+1}\),可以直接三分求答案。时间复杂度 \(\mathcal O(n\log n)\)

CF1957E

基础数论题。

首先,\(C(i,j)=\binom{i}{j}(j-1)!\)

由威尔逊定理(扩展),\((j-1)!\equiv 0 \pmod j\) 当且仅当 \(j\) 不是质数且 \(j\neq 4\)\((j-1)\equiv -1 \pmod j\) 当且仅当 \(j\) 是质数。因此我们只需要对于 \(4\) 和质数分别计算。

\(j\) 为质数时,前面的组合数可以用卢卡斯定理拆开,发现它就是 \(i/j\) 下取整,然后就随便调和级数求个前缀和就行了。\(j=4\) 的时候,可以递推算组合数,然后求二阶前缀和。时间复杂度 \(\mathcal O(n\log n)\),单次问询 \(\mathcal O(1)\)

P4070

在 SAM 上,本质不同子串个数为 \(\sum len_u-len_{fa_u}\),因此每次 extend 的时候动态更新一下答案即可。

CF983E

考虑链上会怎么做:肯定是尽量向右跳。那么很容易通过倍增优化。

在树上也是一样的!两个点都往 lca 尽量跳,跳到还剩一步的位置。如果这时候两个点在一条路线上,那么可以一步到达,否则判断是否都能跳过 lca,如果可以就能两步到达,否则无解。对于判断一条路线,可以二维数点。时间复杂度 \(\mathcal O(n\log n)\)

CF1955H

代价是指数级的,而收益很小,因此容易分析得到 \(r\le 11\),直接状压 dp 即可。

CF1954E

对于一个给定的 \(k\),相当于每次把所有 \(\le k\) 的位置删除后分治,剩下的位置全部减去 \(k\)。对所有 \(k\) 求答案,发现计算次数为调和级数 \(n\log n\)。那么我们只需要对于每个 \(d\) 求出每个位置减掉 \(d\) 之后活着的连续段数量即可求出答案,这个直接扫描线维护 01 / 10 的数量即可。

P4081

建立广义 SAM,对于每个节点维护 tag 表示被哪些串覆盖,求所有的 \(len_u-len_{fa_u}\) 之和即可。

CF1156F

按照值域从小到大 dp 即可,记录选了几张牌,时间复杂度 \(\mathcal O(n^2)\)

CF1542E2

考虑枚举相等的前缀,和不同的第一位分别选了什么。那么不同的逆序对来源就是剩下的后缀,我们就是要计算长度为 \(i\) 的两个排列,逆序对差为 \(j\) 的方案数。直接预处理看似是 \(\mathcal O(n^4)\) 的,也有很多神秘方法优化,比如回退背包等等,但是不如分步转移,因为两个排列无关,轻松优化到 \(\mathcal O(n^3)\)

CF1967B2

\(a+b | b\times \gcd(a,b)\),那么设 \(g=\gcd(a,b)\)\(a=xg,b=yg\),那么 \((x+y)g|yg^2\),即 \((x+y)|yg\)。由于 \(\gcd(x,y)=1\),那么 \(\gcd(x+y,y)=1\),所以 \((x+y)|g\),这样我们可以枚举 \(x,y\),这时候合法的 \(g\) 数量容易 \(\mathcal O(1)\) 计算得到。容易分析出 \(x,y\) 不超过根号级别,时间复杂度线性。

CF1967C

分析每个位置对其树状数组上 \(k\) 级祖先的贡献,是一个组合数,那么我们求 \(k\) 阶树状数组就直接递推即可。求 \(k\) 阶逆就从叶子节点开始解方程即可,时间复杂度 \(\mathcal O(n\log n)\)

CF1967D

建出基环树,然后考虑二分,那么显然每次只需要贪心即可,选择 \(dis\le mid\) 的能达到的编号最小的点。那么问题就是求距离,分类讨论即可。时间复杂度 \(\mathcal O(n\log n)\)

CF1967E1

考虑如何判定特定的 \(a\) 的合法性,抽象成二维平面,把对应位置放上障碍,那么一定会优先向右上走,不能走再向右下走。因此有一个 \(\mathcal O(nm)\) 的 dp。

发现这个问题非常像格路计数,容易分析出一个 \(\mathcal O(n^2/m)\) 的双直线反射容斥做法,拼起来,得到时间复杂度为 \(\mathcal O(n\sqrt n)\)

P4649

保留所有两端点距离为偶数的非树边,现在相当于保留一部分,使得他们在树上互不相交,收益最大。

考虑状压 dp,记录目前有哪些子树还未匹配,每次转移可以舍弃当前点,取所有儿子的任意匹配最大值之和,也可以选若干条路径以当前点为 lca。

P6478

考虑二项式反演,然后就很简单了,直接树形 dp,记录子树内钦定匹配了几组,直接转移即可。时间复杂度 \(\mathcal O(n^2)\)

P6302

容易想到斜率优化,那么对于所有线路,按照 \(x\) 从小到大的顺序 dp 即可,转移略。

P10408

一个典中典套路:考虑折半,对于每个高 \(n/2\) 位的情况,维护低 \(n/2\) 位的高维前缀和。修改的时候修改对应组的高维前缀和,查询的时候调用对应的位置。时间复杂度 \(\mathcal O(n2^n+q2^{n/2})\)

P5504

发现如果某一段开头结尾不同是不优的,因此容易进行 dp,对于每个值维护一个单调队列做斜率优化即可。

P4075

考虑点分治,很容易求出每个点到根的路径的哈希,和模式串哈希进行对比即可,然后用桶统计合法路径数量。

P2567

爆搜出所有合法数字然后进行容斥。

P3175

考虑 min - max 容斥,那么我们需要对于每个二进制位的集合,求出这个集合中的位第一次出现的期望时间,设所有包含至少一个这些位的数的出现概率为 \(p\),那么期望次数就是 \(\frac{1}{p}\),这个求和直接用 FWT 做即可。

P4768

容易想到 kruskal 重构树,那么现在从起点开始可以坐车到达的就是一个子树,我们要求子树中到 \(1\) 的最短路最小值,这很容易预处理出来,时间复杂度 \(\mathcal O(n\log n)\),因为需要向上倍增跳找到子树的根。

P6604

考虑每个数的贡献:最小值肯定是所有经过其的区间。对于其他位置,我们设 \(pre_i\) 为所有以 \(i\) 结尾的区间的最小值之和,\(suf_i\) 为所有以 \(i\) 开始的区间的最小值之和。设最小值位置为 \(p\),那么对于 \(p<i\)\(i\) 的贡献来源于所有以 \(i\) 结尾的区间减去左端点 \(\le p\) 的区间,\(p>i\) 同理,发现这只需要一个前缀和就能算了,时间复杂度 \(\mathcal O(n\log n+q)\)

CF1945H

发现先手一定恰好选两个数。

对于某一位,如果 \(0\) 的数量 \(>2\),那么这一位的按位与一定是 \(0\),否则,如果两个是 \(0\) 的都被选择了,有可能成为 \(1\)。因此和这些 \(0\) 相关的 pair 数量是 \(\mathcal O(n\log V)\) 个,可以一一进行 check。

如果没有选择这些下标,那么按位与一定会得到原序列的按位与,这时候一定会选择 \(\gcd\) 最大的一组,可以调和级数地处理出来,也进行一次 check。每次 check 只需要维护一个桶即可,因此时间复杂度为 \(\mathcal O(n\log^2V+V\log V)\)

P5058

建出圆方树,所求即为 \(A\to B\) 路径上最小圆点编号。

P5825

欧拉数。考虑二项式反演,求钦定 \(k\) 个位置为上升的方案数,可以通过一次二项式反演得到恰好 \(k\) 个位置上升的方案数。钦定的方案数相当于把 \(n\) 个数分进 \(n-k\) 个非空连续段,即 \([x^n](e^x-1)^{n-k}\)(当然也可以理解为对于空连续段进行了一步容斥),展开发现是卷积形式,直接卷即可。时间复杂度 \(\mathcal O(n\log n)\)

P1446

考虑 Burnside 引理,那么现在如果一个点被染色,和他在当前置换的同一个循环内的点都得染成相同颜色,因此直接做一个背包 dp 即可,时间复杂度 \(\mathcal O(mn^3)\)

P3564

\(sl_i\) 为以 \(i\) 为左端点,所有前缀都合法的最远右端点;\(sr_i\) 为以 \(i\) 为右端点,所有后缀都合法的最远左端点,那么一组 \([l,r]\) 合法的条件即为 \(sl_l\ge r,sr_r\le l\),直接扫描线即可。

P3569

(类似 ddp 地)对于线段树每个区间维护开头选正 / 反能得到的最小结尾,合并是容易的。

P3570

先搞出一个合理的暴力做法:枚举相遇的位置,从这个位置向两侧匹配子序列,匹配完后求结束位置的对应的一个前缀和一个后缀内有没有相同元素。

考虑优化这个匹配:发现子序列的元素互不相同,所以每个位置维护一个固定的前驱就行了。至于最后的判断,发现前缀后缀的起始都在不断递增,双指针维护即可。

P3573

定义源点为入度为 \(0\) 的点,汇点为出度为 \(0\) 的点。

\(ds_u,dt_u\) 分别为从某个源点走到 \(u\)\(u\) 走到某个汇点的最长路。

按照拓扑序从小到大求解,把所有拓扑序在 \(u\) 前面的点分在一组,后面的点分在一组,分别设为集合 \(A,B\),那么答案一定来自于 \(A\) 内部某个 \(dt\)\(B\) 内部某个 \(ds\),或者 \(A\to B\) 的一条边 \((x,y)\)\(ds_x+1+dt_y\)。把这个过程抽象成扫描线,每次往 \(A\) 加点,从 \(B\) 删点,发现直接用一个可删堆维护即可。时间复杂度 \(\mathcal O(n\log n)\)

P10516

直接套用势能线段树即可。考虑一次二操作至多带来 \(\sqrt n\) 次修改,复杂度正确。

P10515

发现要求最小的 \(x\) 满足 \((m+1)^{x}\equiv 1\pmod n\),是一个经典的求阶问题。

\(n-1\) 质因数分解,从小到大试除判断即可,时间复杂度 \(\mathcal O(\sqrt n+\log^2 n)\)。事实上容易把 \(\sqrt n\) 优化掉,只要预处理每个数的最小质因子即可。

P2764

(不能重复经过点的)最小路径覆盖。将每个点拆成入点和出点,对于每条边,从对应的出点向入点连边,那么 \(n-\) 最大匹配即为答案。构造方案只需要保留匹配的边跑一遍 dfs 即可。

P10532

一分钟脑筋急转弯,建议早上起床看一眼检验精神状态。

考察组合意义。对于每组 \((i,j)\)\(\lfloor\frac{n}{\max(i,j)}\rfloor\times [\gcd(i,j)=1]\) 实际上在统计满足以下条件的数对 \((x,y)\)

  • \(1\le x,y\le n\)

  • \(g=\gcd(x,y)\),则 \((\frac{x}{g},\frac{y}{g})=(i,j)\)

不难发现每组 \((x,y)\) 都对应了唯一的一组 \((i,j)=(\frac{x}{g},\frac{y}{g})\),因此每个 \((x,y)\) 都被计算恰好一次,答案即为这样的二元组数量 \(n^2\)

P5438

首先考虑最优策略是什么:把所有平方因子除掉之后,把相同的排在一起。那么现在要求有多少 square-free number \(x\in [1,L-1]\) 满足存在 \(c\) 使得 \(c^2x\in [L,R]\)。考虑枚举这个 \(c\),现在相当于区间查询 square-free number 数量,即求 \(mu^2\) 前缀和,可以整除分块求。外层也可以整除分块,对 \(L/i^2\) 相同的进行同时计算,复杂度 \(\mathcal O(n^{4/9})\)

P3207

观察到固定了 \(c,y\) 后,\(x\) 的变化相当于在长度为 \(n/\gcd(d,n)\) 的环上跳,那么可以用并查集维护每个环的下一个有空位的环,以及环上每个点的下一个空位。求出目标位置之后,调整次数只需要求出排列的每个循环。设大小为 \(s\),如果包含 \(0\) 的目标位置,需要 \(s-1\) 次,否则,若 \(s>1\) 则需要 \(s+1\) 次。

CF983D

考虑对着一维扫描线,我们希望每个颜色都能被在第一次看到的位置拿出来记录进答案。用线段树维护当前节点未看过的最大颜色 \(maxv_u\) 和覆盖当前节点的最大颜色 \(maxc_u\)

考虑如何合并信息:如果当前节点没有颜色覆盖,或者儿子覆盖的颜色大于当前节点的颜色,那么 \(max_v\) 可以直接合并两个儿子的较大值;否则,如果左右儿子还有没看过的不超过 \(maxc_u\) 的颜色,只需要考虑 \(maxc_u\) 是否看过即可合并;否则,还需要维护区间最小颜色,这样就可以判断 \(maxc_u\) 是否呈现出来,如果没有呈现出来则没有覆盖。用可删堆维护线段即可,时间复杂度 \(\mathcal O(n\log^2 n)\)

CF1349D

鞅与停时定理应用,前面的推导不记了,只记录一个经典做题套路——势能法。

具体地,对于每个状态定义势能 \(\Phi(A)\),我们希望操作一次,\(\Phi(A)\) 期望 \(-1\),这样期望操作次数就是 \(\Phi(S)-\Phi(T)\) 了,其中 \(S,T\) 表示起始与终止状态。

因为只需要构造这样一个合法的势能函数,因此我们常常把这个 \(1\) 拆成 \(n\)\(\frac{1}{n}\) 或是 \(n\)\(\frac{a_i}{s}\)(其中 \(s=\sum a_i\)),并让每个 \(a_i\) 都满足势能的期望衰减。

接下来往往解一个方程组即可解决,类似于一维随机游走的形式,设一个主元然后代入即可。

同类型问题:CF1025G,CF850F,CF1951G(还没做)

ABC214E

贪心,每次选择一个 \(r\) 最小的限制解决即可。

ABC212G

考虑阶相关的性质容易得到答案为所有约数的欧拉函数之和 \(+1\),直接爆搜即可。注意取模或者开 int128。

ABC212F

对于一条边,下一步走到的位置是固定的,启发我们进行倍增,那么只需要在问询的时候二分出第一条边走哪一条即可,需要特判一下结束位置恰好在点上的情况。

P4223

考虑一个 pair 最终是逆序对的概率,可以把序列分成五段,这样可以用一个 \(7\times 7\) 的矩阵快速幂求出最终两个数所在段落情况,然后用一个树状数组扫一遍即可。

ABC212H

对于一个给定的 \(n\),做法显然是求 \((\sum x^{a_i})^n\) 的异或卷积。这相当于 FWT 后,每个位置取 \(n\) 次幂再 IFWT 回去。

考虑利用 FWT 的线性性,那么求 \(n=1\sim N\) 的答案也是类似的,直接做一个等比数列求和即可。

ABC213H

考虑一个暴力做法:设 \(f_{t,u}\)\(t\) 单位时间走到 \(u\) 的方案数,转移即为枚举 \(u\) 的一条出边指向 \(v\),时间为 \(w\),那么 \(f_{t,u}\) 可以转移到 \(f_{t+w,v}\)

发现这个形式类似一个在线卷积,因此考虑分治 NTT。具体而言,假设目前正在求解 \(t\in [l,r]\) 时的答案,先递归处理 \([l,mid]\),再计算 \([l,mid]\)\([mid+1,r]\) 的贡献。枚举两个点 \(u,v\),计算 \(u\) 的左半区间对 \(v\) 的右半区间的转移,只需要用左半边的 \(f\) 值卷上这条边的 \([0,r-l]\) 时间内的方案数即可。最后再递归计算 \([mid+1,r]\)。时间复杂度 \(\mathcal O(n^2 T\log^2 T)\)

ABC213G

考虑对于每个点集计算这个点集内的点连通,其他点的连通性不管的方案数,然后做一步容斥就得到与 \(1\) 相连的极大连通块恰好是 \(S\) 的方案数了,进而求得答案。前者只需要一个子集枚举 dp 即可,时间复杂度 \(\mathcal O(3^n+2^nn^2)\)

CF1951F

首先,容易发现有解等价于逆序对奇偶性与原排列相同且不超过上下界。

构造只需要贪心的一个一个填就行了。

P4557

首先对两个点集求出凸包,现在需要判断是否存在一个 \(a=b+w,a\in A,b\in B\)

转化一步变成 \(a-b=w\),那么我们希望求出 \(a-b\) 这个凸包,这样就只需要判定 \(w\) 是否在凸包中即可,这是容易的,只需要任意钦定一个点为原点,按照极角序分割成若干个三角形,二分出所在的三角形,判断这个点和原点是否在对应那条边的同侧。

至于求出这个凸包,这是典型的闵可夫斯基和问题,做差分后双指针即可。

P6880

观察到只有最短路树上的边翻转会破坏原最短路,其他的边只需要考虑原最短路或 \(1\to v\to u\to n\) 形最短路,因此只需要跑 \(n\) 次暴力重构即可,时间复杂度 \(\mathcal O(n^3+nm)\)

ABC312Ex

首先将所有的字符串按照最小循环节分类,现在问题等价于:每次询问给出 \(x\),找到目前未被访问的最小的 \(x\) 的倍数并设为访问。

发现直接暴力,记录每种 \(x\) 上次访问位置即可,复杂度显然不超过调和级数 \(\mathcal O(n\log n)\),还需要一个 map 维护,可能会退化成 \(\mathcal O(n\log ^2n)\),但是容易避免这个 log。

P2603

记录相邻边长度比值和夹角后就是个简单的 ACAM 匹配问题。

考虑如何记录,对于前者,可以记录其平方,使其成为有理数;对于后者,可以记录点积和叉积的比值,即 \(\cos\theta/\sin\theta\),这样也会得到一个有理数,约分后存储即可。

P3517

容易想到先二分答案,接着每次二分出右端点跳掉一段,用最小圆覆盖判断。但是这样复杂度是每次判定区间长度之和,达到了平方级别。考虑优化,我们可以先倍增出最大的 \(2^k\) 满足 \([l,l+2^k-1]\) 是合法的,接下来依次考虑 \(2^{k-1},2^{k-2},\dots 2^{0}\) 能否拓展,这样找到一个长度为 \(len\) 的段的时间复杂度是 \(\mathcal O(len\log len)\) 的,总时间复杂度 \(\mathcal O(n\log n\log eps^{-1})\),由于最小圆覆盖的存在,常数极大。

CF903G

将最大流转化为最小割。(常见套路,遇到神秘流题都可以考虑。)

三类边:\(A\) 内部,\(B\) 内部和 \(A\to B\)

发现一定不会断开两条 \(A\) 边:因为断掉较前面的一条之后,必定走不到后面;\(B\) 中同理,考虑较后的一条边。

假设断开了连接 \(u\to u+1\) 的 A 边和 \(v\to v+1\) 的 B 边。那么现在需要从所有 \(A\to B\) 的边中,断开所有 A 侧端点 \(\le u\),B 侧端点 \(>v\) 的边。容易发现,对于一个 \(u\),最优的 \(v\) 唯一且不变(修改只会变化 \(a\)),因此可以先扫描线一遍求出每个 \(u\) 的最优 \(v\),接下来问题就变成了单点修改,查询全局 max,直接用可删堆维护即可。时间复杂度 \(\mathcal O(n\log n)\)

P4128 / P4727

一个置换能被分解成多个循环。分开考虑这些循环,将边分成两类:循环内的和循环间的。设循环大小为 \(c_1,c_2\dots c_k\)。对于第一种边,在一个环上连一条边,只有 \(\lfloor c_i/2 \rfloor\) 种(按照距离区分);对于第二种边,相当于初始在 \((0,0)\),每次两维坐标都 \(+1\),并分别对 \(c_i,c_j\) 取模,那么应当出现 \(c_ic_j/\operatorname{lcm}(c_i,c_j)\) 个环,即 \(\gcd(c_i,c_j)\) 种不同的边。

因此对于每种置换,我们可以轻松求出答案:\(m^{\sum\limits_{i}c_i/2+\sum\limits_{i,j}\gcd(c_i,c_j)}\),得到一个 \(\mathcal O(n!\times n)\) 的做法。

发现很多排列的置换环大小集合等价,事实上,只有 拆分数 种不同集合,因此考虑搜出这些集合,计算方案数。得到一个置换环的方案数显然是 \(\frac{n!}{\prod c_i \prod cnt_i}\),其中 \(cnt_i\) 表示环长 \(i\) 出现的次数。最后答案还要除掉 \(n!\)

注意预处理 gcd 卡常。

P5401

条件相当于限制个数为奇数的不超过 \(n-2m\) 个,那么考虑二项式反演,计算钦定 \(n-2m\) 个奇数的方案数,用 EGF 推导(奇数的 EGF 即 \((e^{x}-e^{-x})/2\))得到卷积形式的式子,再卷积做二项式反演。

P4709

CF1969E

贪心的策略是显然的:每次从当前位置往后扫,扫到不合法的位置就换成一个没出现过的数,把序列断开继续做。

那么问题在于如何判定一个区间是合法的。考虑每次右端点 \(r\) 增加 \(1\),只需要判定不同的 \(l\) 和当前 \(r\) 组合成的区间即可。用线段树维护每个 \(l\) 对应当前 \([l,r]\) 中出现 \(1\) 次的数的数量,那么发现每次移动只会改变 \(\mathcal O(1)\) 个关于前两次出现位置的区间,直接维护区间 min 即可,时间复杂度 \(\mathcal O(n\log n)\)

posted @ 2024-05-06 23:09  PetitSouris  阅读(113)  评论(1)    收藏  举报