2月杂题

1.P3920 [WC2014]紫荆花之恋

离线怎么做?考虑把点分树建出来。

在线怎么做?考虑定期重构,暴力查散点,跳点分树查整点。

2.CF1063F String Journey

\(O(n\sqrt{n})\) :观察到答案不超过 \(\sqrt{n}\) ,暴力即可。

\(O(n\log n)\) :考虑 \(dp_i\) 表示 \([i,n]\) 这个串的答案,则 \(dp_i\le dp_{i+1}+1\)

倒着 dp ,每次判断 \(dp_i\) 是否 \(\geq x\) ,只需要做 \(O(n)\) 次判断。

相当于要找到一个 \(j\) 使得 \(j\geq i+x,dp_j\geq x-1,\max(lcp(i,j),lcp(i+1,j))\geq x-1\)

注意到 \(i+x\) 单调不增。lcp 利用 SAM 处理,则变成 fail 树上的单点修改,子树 max ,线段树维护即可。

3.P4649 [IOI2007] training 训练路径

注意到没有偶环,相当于每个非树边覆盖的路径,长度是奇数,且两两不交。

如果一个路径 \(i\) 覆盖了一条边,就给这个边染上颜色 \(i\)

\(dp_{x,i}\) 表示处理了子树 \(x\)\(x\)\(fa\) 染色为 \(i\) ,最大的权值。我们对于每个路径,在 lca 处算贡献。

转移是一个状压 dp 的过程,复杂度 \(O(2^{10}(n+m)+nm)\)

4.LOJ2765「JOI 2013 Final」 冒泡排序

观察到交换的 \(a_i,a_j(i<j)\) 一定满足 \(a_i>a_j\) ,且 \(a_i\)\([1,i]\) 中严格最大值,\(a_j\)\([j,n]\) 中严格最小值。

对于 \(a_i>a_k>a_j,i<k<j\) ,对答案有 \(2\) 的贡献。把可能的 \(i\)\(j\) 拎出来,并以点 \((i,j)\) 表示交换 \(a_i,a_j\) 的答案,那么 \(k\) 贡献的范围一定是一个矩阵。

注意 \(a\) 可能有相同的,有一些特殊情况,处理是类似的。

由此扫描线即可。复杂度 \(O(n\log n)\)

5.P6846 [CEOI2019] Amusement Park

首先,一个 DAG ,把所有边反向,得到的还是 DAG 。

所以答案是 \(m/2\) 乘上定向的方案数。

考虑钦定一些点作为 DAG 中入度为 \(0\) 的点,但是这样会算重。考虑,如果钦定 \(x\) 个点,就乘上 \((-1)^{x-1}\) 的容斥系数,这样就好了。

\(f_S\) 是子集 \(S\) 的答案,\(g_S\)\([S是独立集](-1)^{|S|-1}\) ,则 \(f_S=\sum\limits_{T\subset S}g_Tf_{S-T}\)

复杂度是 \(O(3^n+2^nn^2)\) 。可以用子集卷积优化到 \(O(2^nn^2)\)

6.CF1787H Codeforces Scoreboard

先化成 \(\sum max(0,b_i-k_i*t)\) 的形式。我们可以看成每个式子在 \(0\)\(b_i-k_i*t\) 中选一个。

考虑这些选了的。首先 \(b\) 就不影响了,并且我们会按 \(k\) 从大到小插入式子。

所以把全局的式子排序,令 \(dp_{i,j}\) 表示考虑前 \(i\) 个,选了 \(j\) 个的最大权值,则 \(dp_{i,j}=\max(dp_{i-1,j-1}+b_i-k_ij,dp_{i-1,j})\) 。令 \(z_{i,j}=dp_{i,j}-dp_{i,j-1}\)

考虑转移,一开始猜测 \(dp_i\) 是上凸的,即 \(z_{i,j}\geq z_{i,j+1}\) 。然后维护差分数组。其实是对的,但是不好证明。

根据证明中的障碍,进一步猜测 \(z_{i,j}-z_{i,j+1}\geq k_i\) ,这反而更好证明,且更好利用。证明如下:

考虑归纳证明,假设 \(z_1\)\(z_{i-1}\) 都是满足条件的。

考虑转移的过程, \(max\) 式子中的两个值,作差法得到 \(b_i-k_ij-z_{i-1,j}\)\(j\) 变成 \(j+1\) ,前面这个式子的增加量就是 \(z_{i-1,j}-z_{i-1,j+1}-k_i\geq k_{i-1}-k_i\geq 0\) 。所以这个式子是单调不减的。

\(k_{i-1}-k_i\geq 0\) 是因为我们已经从大到小排序了。

我们令 \(x\) 是第一个满足 \(b_i-k_ij-z_{i-1,j}\geq 0\)\(j\)\(f\) 变化时 \(z\) 的变化:相当于 \(z_{i,j}=z_{i-1,j}(1\le j<x)\)\(z_{i,x}=b_i-k_ix\) ,\(z_{i,j}=z_{i-1,j-1}-k_i(j>x)\) 。(如果不想看证明,即可用平衡树维护这个过程。)

对于 \(j\le x-2\)\(z_{i,j}-z_{i,j+1}=z_{i-1,j}-z_{i-1,j+1}\geq k_{i-1}\geq k_i\) 。对于 \(j=x-1\)\(z_{i,j}-z_{i,j+1}=z_{i-1,x-1}-(b_i-k_ix)\)

因为对于 \(j<x\) ,都有 \(b_i-k_ij-z_{i-1,j}<0\) ,则 \(b_i-k_ix+k_i-z_{i-1,x-1}<0\)\(z_{i-1,x-1}-b_i+k_ix> k_i\)

对于 \(j=x\)\(z_{i,j}-z_{i,j+1}=(b_i-k_ix)-z_{i-1,x+1}\) 。同 \(j=x-1\) 的证明,可以得到这是 \(\geq k_i\) 的。

对于 \(j>x\) ,同 \(j\le x-2\) 的证明,\(z_{i,j}-z_{i,j+1}=(z_{i-1,j-1}-k_i)-(z{i-1,j}-k_i)=z_{i-1,j-1}-z_{i-1,j}\geq k_{i-1}\geq k_i\)

综上,对于任意 \(j>0\) ,有 \(z_{i,j}-z_{i,j+1}\geq k_i\) ,结论成立。

7.ABC288Ex A Nameless Counting Problem

我们计算 \(f_i\) 表示 \(i\) 个互不相同的数的答案,则之后同时插入两个数,答案为 \(\sum f_{n-2i}\tbinom{m+i}{i}\)

考虑利用容斥计算,考虑任意两个数都要满足 \(a_i\ne a_j\) ,我们钦定一些二元组 \((i,j)\) 满足 \(a_i=a_j\) 进行容斥,连成的每个连通块的所有数要相等。

如果已经确定一个大小为 \(n\) 的连通块然后内部连边,则所有方案的系数和为 \((-1)^{n-1}n!\) ,可以归纳发现。

钦定连通块的过程类似于一个 EGF , \(O(n^3)\) 卷一下就好了。就是求 \(g_{i,j}\) 表示 \(i\) 个点,\(j\) 个大小为奇数的连通块(为偶数的,直接乘上 \(m+1\),不影响异或和) 的方案数。

再算一个 \(h_i\) 表示任意 \(i\) 个数的答案。则 \(f_i=\frac{1}{i!}\sum g_{i,j}h_j\)

\(h\) 直接数位 dp,复杂度是 \(O(n^3\log m)\)

8.CF1787I Treasure Hunt

神题

我们设定 \(q\) 是最大前缀和的位置。考虑如果选择 \(l\le q<r\) ,那么把 \(r\) 赋值为 \(q\) ,权值增加量为 \(s_q-s_r\le 0\) ,一定是不劣的。所以一个序列的权值是:最大前缀和+最大子段和。

最大前缀和的和容易利用单调栈 \(O(n)\) 算出。

最大子段和的和?考虑分治,计算跨越 mid 的区间的权值和。

\(i>mid\) 时,令 \(a_i\) 表示 \(j\in (mid+1,i]\) 的最大的 \(s_j\)\(b_i\) 表示 \((mid+1,i]\) 的最大子段和。

\(i\le mid\) 时,定义类似。

则问题转化为计算 \(\sum \sum \max\{a_i+a_j,b_i,b_j\}\) ,这是二维偏序问题,可以 \(O(n\log n)\) 计算,则总复杂度为 \(O(n\log^2 n)\)

有结论:\(a_i-b_i(i>mid)\) 是单调不降的,\(a_i-b_i(i\le mid)\) 是单调不增的。利用这个就能维护三个指针,进行计算了,复杂度 \(O(n\log n)\)

给出 \(i>mid\) 时的证明:

令考虑到 \(i\) 时,最大字段和是 \(s_r-s_l\),最大前缀和是 \(s_q\) 。则根据本文一开始的讨论,\(r=q\)\(l>q\)

如果 \(r=q\) ,则加入 \(i+1\)\(\Delta a=\Delta b=\max(s_{i+1}-s_q,0)\)

\(l>q\) :则加入 \(i+1\) 时分情况讨论:

  1. \(q\) 将变成 \(i+1\)\(\Delta a=s_{i+1}-s_q\)。发现 \(\Delta b\le s_{i+1}-s_r\le s_{i+1}-s_q=\Delta a\)

  2. \(q\) 不变,则 \(\Delta a\geq 0\)\(\Delta b =0\)

就证完了 \(\Delta a\geq \Delta b\)

9.CF1785E Infinite Game

考虑在状态中记下:\(4\) 种初始比分,经过串 \(S\) 后会变成什么。

则最后,\(i\) 经过 \(S\) 变成 \(p_i\) ,会形成一个基环树。根据 0:0 能到达的环的权值和来判断结果。(权值就是指 A赢的次数 - B赢的次数)

枚举哪些比分最后会在环上的集合 \(S\),则是 \(dp_{i,j,t0,t1,t2,t3}\) 的形式,转移就好了。如果符合枚举的 \(S\) ,就统计如答案。

这样做是 \(O(n^2)\) ,常数 \(4^4*2^4*2=2^{13}\) 。跑不满,跑满了也能过(

10.P7985 [USACO21DEC] Paired Up P

显然,如果钦定了参与匹配的牛,他们一定按坐标从小到大依次匹配。

T=1 时记 \(f_{i,j}\) 表示第一类牛考虑到 \(i\) ,第二类牛考虑到 \(j\) 。因为满足最大就保证最大,所以 dp 一下就好了。

T=2 时需考虑“极大”的限制。

\(f_{i,j,k,l}\),其中 \(k\) 表示第一类牛最后一个没考虑的,\(l\) 同理。

\(k\)\(l\) 只用记靠后的一个。因为 \(k\)\(l\) 差一定 \(>L\) ,那么靠前的那个点,无法影响更后面的点。

现在就变成 \(f_{i,j,k}\) 了。考虑何时 \(k\) 能变成另一类牛?

比如 \(k\) 是第一类,必定是某个时刻,\(i=k\) ,然后第一类在 \(i+1\) 后,第二类在 \(j+1\) 后,匹配连续的一段,使得下一个未匹配的第二类 \(t\),满足 \(x_t>x_k+L\)

于是状态就简化成 \(f_{i,j,0/1}\) 了,\(O(n^2)\) 可通过本题。

11.ABC215H Cabbage Master

考虑霍尔定理,选择一个右端点的集合。则在左端点的并集相同的情况下,一定会尽量多选来卡限制。

\(f_{S}\) 是左端点集合 \(S\) ,使并集 \(T\subseteq S\) 的情况下的最大的 \(\sum b\)

\(g_{S}\)\(S\) 集合的 \(\sum a\),则第一问答案是 $an=\min {f_S-g_S+1}$ ,其中 \(f_S\ne 0\)

考虑第二问,我们删去 \(an\) 个小球后,令这些小球覆盖的左端点集合为 \(T\) ,则一定存在 \(T\subseteq S\) 使得 \(f_S-g_S+1=an\)

一个 \(T\) 是否合法就很容易判断。而这个并集恰好为 \(T\) 的限制,可以考虑构造 \(e_S=\tbinom{g_S}{an}\) ,然后 IFMT 一下。

12.ABC289Ex Trio

题外话:f[i-l]=h[i] 写成 f[i]=h[i-l] 导致没有场切。以后打 ABC 只做 G 和 Ex,节省时间。(其实是这场被 F 卡了)

考虑 “\(T\) 是第一次三点合一的时刻” 这个限制,容斥,钦定一些时间会三点合一。

则算一个 \(f_i\) 表示经过 \(i\) 刻,从初始状态变成三点合一的方案数,\(g_i\) 表示经过 \(i\) 刻,从三点合一变成三点合一的方案数。这俩都是能一遍卷积算出来的。

然后就 分治 FFT/多项式求逆 。

13.LOJ3075 「2019 集训队互测 Day 3」组合数求和

神题。

专门开了一篇写做法。

自己没想到的东西:

  1. 拆模数,求模数为 \(p_i^{c_i}\) 的答案后 CRT 合并。这是很常见的方法。

  2. 处理不好求逆元的多项式除法的神秘方法。

14.「WC2023 / CTS2023」楼梯

发现想清楚代码就不难写。

我们用 01 序列刻画轮廓线,从右上角开始,往下走为 0 ,往左走为 1。

用权值线段树维护,位置 \(i\) 表示第 \(i\)\(0\) 后有多少个 \(1\) ,则修改都是容易实现的。

考虑查询。发现一个子楼梯对应了一个子段 \([l,r]\) ,满足 \(a_l=0,a_r=1\) ,且 \(r-l\) 就是边界格数。

现在查询相当于要取一对 \(l,r\) 使得 \(a_l=0,a_r=1,r-l=q\)

由题,\(a_0=0,a_n=1\) ,且 \(n\)\(q\) 倍数。那么考虑二分,初始 \(l=0,r=n/q\) 。如果 \(a_{q*mid}\)\(1\) ,就令 \(r:=mid\) ,否则 \(l:=mid\)

\(a\) ,以及 \(l,r\) 后输出坐标,都可以利用线段树实现。

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

15.AGC061C First Come First Serve

第一次场切 AGC 的 C,很激动。但是这场 A 做得太慢了(

简化题意:有两个长度为 \(n\) 的单调递增序列 \(l\)\(r\) ,并且不存在 \(l_i=r_j\) 。你可以使 \(a_i\) 等于 \(l_i\) 或者 \(r_i\)

一个排列 \(p\)\(p_i\) 表示 \(a\) 中第 \(i\) 小的数的下标。问有多少种不同的 \(p\)\(1\le n\le 5*10^5\)

做法:

考虑对于 \(p\) ,怎么构造出 \(a\)。可以从左往右贪心构造:如果 \(a_{p_{i-1}}<l_{p_i}\) ,则 \(a_{p_i}=l_{p_i}\) ,否则 \(a_{p_i}=r_{p_i}\)

而一组 \(a\) 只会对应一个 \(p\) 。则一组 \(a\) 会在它对应的 \(p\) 的构造中被“采用”,当且仅当:如果存在 \(i\) 使 \(a_i=r_i\) ,则必须存在 \(a_j\) 使得 \(l_i<a_j<r_i\)

由此,考虑容斥处理这个限制。钦定一些 \(i\) ,使得 \(a_i=r_i\) ,且不存在 \(j\) 使 \(l_i<a_j<r_i\) 。 我们称这个限制为,\([l_i,r_i]\) 都被 \(i\) 覆盖了。

考虑钦定了的数,它们覆盖的区间两两不交。

其次,如果有一个 \(j\) ,两端都被覆盖了,则对答案贡献为 \(0\) ;否则,贡献为 \(2^{n-\sum r_i-l_i}\)

如果 \(j\) 两端都被覆盖,由于 \(l\)\(r\) 单调递增,一定是相邻两个钦定了的区间 \(i_1,i_2\),使得 \(i_1<j<i_2,l_j<r_{i_1},r_j>l_{i_2}\)

我们记 \(dp_i\) 表示,当前钦定集合末尾为 \(i\) ,所有方案的贡献和。

\(i_1\) 能转移到的 \(i_2\) 一定是一个后缀,而这个范围可以二分两次求出。由此,我们以 \(O(n\log n)\) 的复杂度解决了此题。

16.CF765F Souvenirs

考虑把询问按右端点排序,然后加入 \(a_i\) 时,我们先考虑 \(a_j\le a_i\) 的数对。

如果已经取到一个 \(a_j\le a_i\) ,则对于 \(k<j\) ,必须满足 \(a_k-a_j>a_i-a_k\) ,这个 \((k,i)\) 才对答案的更新有用。

所以我们加入 \(a_i\) 时就一直按照上面的限制找下一个 \(j\) ,由于 \(a_i-a_j\) 每次会减半,所以 \(j\) 只有 \(O(\log n)\) 个。找 \(j\) 可以主席树实现,更新答案用 BIT。

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

17.UOJ310 【UNR #2】黎明前的巧克力

FWT 练习题。

回忆 FWT :令 \(o(S,T)=popcount(S\cap T)\)

我们来回忆一下FWT:\(a'_S=\sum (-1)^{o(S,T)}a_T\) 。以及 IFWT, \(Na_S=\sum (-1)^{o(S,T)}a'_T\)

把题意写成集合幂级数的形式: \([x^0]\prod \{1+2x^{p_i}\}\)

\(1+2x^{p_i}\) 施加 FWT 得到 \(F_i(x)\) ,考虑 \([x^S]F_i(x)\) ,如果 \(o(S,p_i)\) 为奇数,则为 \(-1\) ,否则为 \(3\)

那我们对于每个 \(S\) ,我们想算 \(\prod [x^S]F_i(x)\) ,只需统计出 \(\sum (-1)^{o(S,p_i)}\) 即可。这恰好能用 FWT 计算。

而答案恰好是 \(\sum \prod [x^S]F_i(x)\) ,因为 \(o(0,S)=0\)

18.CF1672I PermutationForces

神题,难想难写。

\(c_i\) 初始为 \(|i-p_i|\) 。我们令第 \(i\) 个点是 \((i,p_i)\)

显然一个贪心策略是每次删掉 \(c_i\) 最小的 \(i\) 。而对其他点的影响,就是两个矩形内的点 -1。

问题是怎么维护 \(c\) ,怎么找最小。暴力 KDT 显然过不去。

我们以主对角线为界,分上下考虑。以上半部分为例,一个点 \(i\)\(c_i\) 可能最小,当且仅当 \(p_i\) 是后缀最小值,读者自证不难。

只考虑这些点的话,矩阵加实际上就转化成了区间加。但删掉一个点,就会有一些新的点进入候选方案。可以用线段树二分来寻找这些点。

还有一个问题是,新加入一个点,怎么算它此时的 \(c_i\) 。可以用树状数组维护。

细节很多。我写得很烦。

代码(3.5k)
// LUOGU_RID: 102160828
#include<bits/stdc++.h>
using namespace std;
int n,p[501000];
struct BIT{
	int tr[501000];
	inline void add(int x,int z){for(;x<=n;x+=(x&-x))tr[x]+=z;}
	inline int ask(int x){int s=0;for(;x;x-=(x&-x))s+=tr[x];return s;}
}K[2][2];
const int I=1e9;
struct qt{int f,is;};
qt min(qt a,qt b){return (a.f<b.f)?a:b;}
qt max(qt a,qt b){return (a.f>b.f)?a:b;}
struct SGT{
	qt mi[2010000],mi2[2010000],mx[2010000];
	int tag[2001000];
	inline void build(int p,int l,int r){
		mi[p]=(qt){I,l},mi2[p]={I,l};
		mx[p]=(qt){-I,l};
		if(l==r)return;
		int mid=(l+r)>>1;
		build(p<<1,l,mid),build(p<<1|1,mid+1,r);
	}
	inline void ad(int x,int z){tag[x]+=z,mi2[x].f+=z;}
	inline void pd(int x){ad(x<<1,tag[x]),ad(x<<1|1,tag[x]),tag[x]=0;}
	inline void up(int p,int l,int r,int x,int y,int y2,int z){
		if(l==r){mi[p]=(qt){y,x};mi2[p]=(qt){z,x};mx[p]=(qt){y2,x};return;}
		pd(p);int mid=(l+r)>>1;
		if(x<=mid)up(p<<1,l,mid,x,y,y2,z);
		else up(p<<1|1,mid+1,r,x,y,y2,z);
		mi[p]=min(mi[p<<1],mi[p<<1|1]);
		mi2[p]=min(mi2[p<<1],mi2[p<<1|1]);
		mx[p]=max(mx[p<<1],mx[p<<1|1]);
	}
	inline void up2(int p,int l,int r,int x,int y,int z){
		if(y<l||x>r)return;
		if(x<=l&&r<=y)return ad(p,z);
		pd(p);int mid=(l+r)>>1;
		up2(p<<1,l,mid,x,y,z),up2(p<<1|1,mid+1,r,x,y,z);
		mi[p]=min(mi[p<<1],mi[p<<1|1]);
		mi2[p]=min(mi2[p<<1],mi2[p<<1|1]);
		mx[p]=max(mx[p<<1],mx[p<<1|1]);
	}
	inline qt ask1(int p,int l,int r,int x,int z){
		if(mi[p].f>z)return (qt){I,0};
		if(l==r)return mi[p];
		int mid=(l+r)>>1;
		if(x<=mid)return ask1(p<<1,l,mid,x,z);
		qt cp=ask1(p<<1|1,mid+1,r,x,z);
		if(cp.is)return cp;
		return ask1(p<<1,l,mid,mid,z);
	}
	inline qt ask2(int p,int l,int r,int x,int z){
		if(mi[p].f>z)return (qt){I,n+1};
		if(l==r)return mi[p];
		int mid=(l+r)>>1;
		if(x>mid)return ask2(p<<1|1,mid+1,r,x,z);
		qt cp=ask2(p<<1,l,mid,x,z);
		if(cp.is<=n)return cp;
		return ask2(p<<1|1,mid+1,r,x,z);
	}
	inline qt ask3(int p,int l,int r,int x){
		if(mx[p].f<x)return (qt){-I,n+1};
		if(l==r)return mx[p];
		pd(p);int mid=(l+r)>>1;
		qt cp=ask3(p<<1,l,mid,x);
		if(cp.is>n)return ask3(p<<1|1,mid+1,r,x);
		else return cp;
	}
}T[2][2];
int main(){
	scanf("%d",&n);
	int M=n+1;
	for(int i=0;i<2;i++)for(int j=0;j<2;j++)T[i][j].build(1,1,n);
	for(int i=1;i<=n;i++)scanf("%d",&p[i]);
	for(int i=n;i;i--)
		if(p[i]>=i){
			if(M>p[i])M=p[i],T[0][0].up(1,1,n,i,p[i],p[i],p[i]-i);
			else T[0][1].up(1,1,n,i,p[i],p[i],I);
		}
	M=n+1;
	for(int i=1;i<=n;i++)if(p[i]<i){
		if(M>n+1-p[i])M=n+1-p[i],T[1][0].up(1,1,n,n-i+1,n-p[i]+1,n-p[i]+1,i-p[i]);
		else T[1][1].up(1,1,n,n-i+1,n-p[i]+1,n-p[i]+1,I);
	}
	int ans=-1,step=n;
	while(step--){
		int o=((T[0][0].mi2[1].f<T[1][0].mi2[1].f)?0:1);
		int x=T[o][0].mi2[1].is;
		int y=T[o][0].mi2[1].f;
		T[o][0].up(1,1,n,x,I,-I,I);
		ans=max(ans,y),y=(o?(n+1-p[n+1-x]):p[x]);
		K[o][0].add(x,1),K[o][1].add(y,1);
		int ii=T[o][0].ask3(1,1,n,y).is;
		if(ii<=x)T[o][0].up2(1,1,n,ii,x,-1);
		ii=T[o^1][0].ask3(1,1,n,n-y+1).is;
		if(ii<=n-x+1)T[o^1][0].up2(1,1,n,ii,n-x+1,-1);
		qt al=T[o][0].ask1(1,1,n,x,n),ar=T[o][0].ask2(1,1,n,x,n);
		while(al.is+1<ar.is){
			qt nx=T[o][1].ask1(1,1,n,ar.is-1,min(ar.f,n+1)-1);
			if(al.is>=nx.is)break;
			int u=nx.is,y=(o?(n+1-p[n+1-u]):p[u]);
			int cs=y-u;
			cs-=(K[o][0].ask(n)-K[o][0].ask(u))-(K[o][1].ask(n)-K[o][1].ask(y));
			cs-=K[o^1][0].ask(n-u+1)-K[o^1][1].ask(n-y+1);
			T[o][1].up(1,1,n,u,I,-I,I);
			T[o][0].up(1,1,n,u,y,y,cs);
			ar=nx;
		}
	}
	return printf("%d",ans),0;
}

18.P5900 无标号无根树计数

学习 GF ing。

\(n\) 个点的无标号有根树方案 \(f_n\) ,无标号无根树方案为 \(g_n\) 。如果已经计算出 \(f_i\) ,我们考虑拎出重心,得到 \(g_n=f_n-\sum\limits_{2j>n}f_jf_{n-j}\) 。特别地,如果 \(n\) 为偶数,还要减去 \(\dbinom{f_{n/2}}{2}\)

如何算 \(f_i\) ?考虑枚举有几个儿子,根据 burnside ,枚举所有置换求不动点的平均值。

\(F(x)=\sum f_ix^i\) 。一个大小为 \(k\) 的环,这个环代表的 \(k\) 个树都要相同,然后内部连边方案 \((k-1)!\) ,则它的 EGF 为 \(F(x^k)\frac{(k-1)!}{k!}=\frac{F(x^k)}{k}\)

把他们拼起来,则 \(f_i=[x^{i-1}]e^{\sum \frac{F(x^k)}{k}}\) 。(注意这里 EGF 的 \(n!\) 和求平均数的 \(\frac{1}{n!}\) 抵消了).

即:\(F(x)=xe^{\sum \frac{F(x^k)}{k}}\) 。我们令 \(E(x)=\sum \frac{F(x^k)}{k}\)\(F(x)=xe^{E(x)}\)

考虑两边求导: \(F'(x)=e^{E(x)}+xe^{E(x)}E'(x)\)

\(xF'(x)-F(x)=xE'(x)F(x)\)。而 \(xE'(x)\) 可以展开为 \(\sum_{j\geq 1} \sum_{i\geq 1} x^{ij}\frac{f_{j}}{j}\)

不难发现可以分治 FFT 解决:令 \(g_i=\sum\limits_{d|i} f_d\) ,则 \(f_1=1\)\(f_i=\frac{1}{i-1}\sum\limits_{j=1}^{i-1} f_jg_{i-j}(i>1)\)

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

19.ABC230H Bullion

和上面这个题类似,令 \(A(x)=exp(\sum\limits_{a\in S} \frac{x^{a}}{a})\)\(S\) 是题中给出的金条体积的集合)(这里需要 exp)。

答案生成函数为 \(F(x)\)\(E(x)=\sum \frac{F(x^k)}{k}\) ,则 \(F(x)=x(e^{E(x)}A(x)-1)\)

和上面类似的化简可得 \(xF'(x)-F(x)=(\frac{xA'(x)}{A(x)}+xE'(x))(F(x)+x)\) 。分治 FFT 计算即可。

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

20.ARC156D Xor Sum 5

考虑最后会贡献给答案的,肯定是 \([x^s](\sum x^{a_i})^k\) 为奇数的 \(s\)

然后你发现,\((\sum x^{a_i})^2\) 在模 \(2\) 时得到 \(\sum x^{2a_i}\)

那我们将 \(k\) 二进制拆分,就得到 \(\prod\limits_{p\in k} (\sum x^{a_i2^{p}})\) 。由此可以从低到高数位 dp 。

21.ARC156E Non-Adjacent Matching

这种题一般都是先找一些必要条件,然后证充分性。

首先度数和 \(S\) 一定是偶数;其次考虑相邻两个不能连边能得到什么,卡一些极端情况试试,想到 \(x_i+x_{i+1}\le \frac{S}{2}\)

发现这个确实是充分的,考虑 \(b_i=\frac{S}{2}-x_i-x_{i+1}\) ,则连边 \((u,v)\) 等同于除了 \(b_u,b_{u+1},b_{v},b_{v+1}\) 这四个数都要减 \(1\) ,最后 \(b\) 要变成全 \(0\)

现在我们要让 \(b\) 一直非负。你会发现,如果 \(b\) 不超过两处为 \(0\) ,那操作是容易的;如果有三处为 \(0\) ,那肯定有相邻的 \(b_i=b_{i+1}=0\) ,操作也是容易的。

\(0\) 的位置只会有不超过三处,读者自证不难。

然后计数就是容斥钦定一些位置 \(b_i+b_{i+1}>\frac{S}{2}\) ,则要么钦定一处,要么钦定两处且相邻。

就容易算了,复杂度 \(O(n^2+k)\)

22.P4128 [SHOI2006] 有色图/P4727 [HNOI2009]图的同构计数

复习 polya 定理。考虑枚举置换 \(p\) 计算不动点,即 \((i,j)\)\((p_i,p_j)\) 颜色相同。

令每个环的大小分别为 \(x_1,x_2,…,x_k\) ,则令 \(A=\sum \left\lfloor\dfrac{x_i}{2}\right\rfloor+\sum\limits_{i=1}^k\sum\limits_{j=i+1}^k \gcd(x_i,x_j)\) ,则不动点为 \(m^A\)

枚举 \(p\) 不现实,考虑枚举 \(n\) 的划分 \(x\),填位置系数 \(\frac{1}{x_i!}\) ,内部连环系数 \((x_i-1)!\) ,则对答案贡献为 \(A(x)\frac{n!}{\prod x_i}\)

注意到相等的 \(x\) 是会算重的,如果 \(i\)\(x\) 出现 \(c_i\) 次,则还要乘上 \(\frac{1}{\prod c_i!}\)

最后除以 \(n!\)

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

23.CF1784F Minimums or Medians

考虑已经确定了哪些位置会被删,我们怎么判断能被构造出来。

发现含有 \(1\) 的这一段很重要,这一段越长,后面的操作越自由。

我们来找必要:每一段长度都是偶数;最右的位置 \(\le n+k\) ;不包含 \(1\) 段要满足 \(l+r\geq 2n+1\)

手玩一下发现这很充分,于是对着这个计数就好了,复杂度 \(O(n)\)

感觉这很 ATC,就是手玩找结论。

24.AGC061D Almost Multiplication Table

好神啊,这种调整法以前没见过捏。

先二分答案,得出 \(x_iy_j\) 的上下界。

考虑把 \(x\) 设为 \(x_i=i\) ,这一定是严格最小的 \(x\) :如果存在合法解 \(x'\),一定有 \(x_i\le x'_i\)

得到 \(x\) 后,如果我们只考虑上界,一定能得到唯一的一组 \(y\) ,严格最大。但这样就不满足下界了,再去调整 \(x\) 。一直做下去,直到找到合法解。

由于这样的操作每一步都是最优的,所以存在合法解,一定能到达。

考虑如何保证复杂度:我们钦定 \(x_n\le y_m\) ,如果 \(x_n>y_m\) 就退出调整,再对称的做一遍 \(y_m\le x_n\)

这样的话,由于 \(x_ny_m\le a_{i,j}+k\) ,所以 \(x_n\) 只会到达 \(O(\sqrt{V})\) 的级别。

由于每次调整都会使至少一个 \(x\) 增加,所以调整轮数是 \(O(n\sqrt{V})\) 级别,这样子就保证了复杂度!

算上二分和每次调整的复杂度,总复杂度 \(O(n^3\sqrt{V}\log V)\)

25.P5434 有标号荒漠计数/LOJ6569 仙人掌计数

考虑一个 有根 仙人掌的 EGF 为 \(F(x)\) 。这里钦定一个根是因为仙人掌本身结构与树相似。

考虑这个根,它会被一些边和环覆盖。 如果它在一个环上,则环上面另外 \(i-1\) 个点分别挂了一颗仙人掌(此处体现了有根的作用)的 EGF 是 \(\frac{1}{2}\sum\limits_{i\ge 2}F^i(x)\)

除以 \(2\) 是因为环正着排和反着排是相同的。如果它在一个边上,则有 EGF \(F(x)\)

我们会把环和边叠起来,所以得到 \(F(x)=x*exp(\frac{1}{2}\sum\limits_{i\ge 2}F^i(x)+F(x))=xexp(\frac{2F(x)-F(x)^2}{2-2F(x)})\)

我们来牛顿迭代,令 \(G(F(x))=x*exp(\frac{1}{2}\sum\limits_{i\ge 2}F^i(x)+F(x))=xexp(\frac{2F(x)-F(x)^2}{2-2F(x)})-F(x)\)

\(t=F_0(x)\)\(P(t)=xexp(\frac{2t-t^2}{2-2t})\) ,可以得到 \(F(x)=t-\frac{P(t)-t}{P(t)\frac{t^2-2t+2}{2t^2-4t+2}-1}\)

对着算就好了,复杂度 \(O(n\log n)\) ,但是常数很恐怖。

26.ABC222H Beautiful Binary Tree

考虑每个 \(a_i=1\) 的位置,都要进行一次 \(v=i\) 的操作。所以根节点一定为 \(1\) ,且 \(n-1\) 次操作只会在初始 \(a_i=1\) 的点进行。

如果存在两个相邻的点都是 \(0\) ,显然就得多跳一次,不合法了。所以题目条件等同于:二叉树,根节点为 \(1\) ,一共 \(n\)\(1\) ,叶子都是 \(1\) ,不存在相邻的 \(0\) ,求方案数。

考虑 \(f_{i,0/1}\) ,分别表示根为 \(0/1\) 的答案。把它写成生成函数的形式:\(F_0,F_1\) ,则有 \(F_0=(F_1+1)^2-1\) (-1是因为叶子节点必须是 \(1\)),\(F_1=x(F_0+F_1+1)^2\)

\(x=\frac{F_1(x)}{(1+3F_1(x)+F_1(x)^2)^2}\) 。令 \(G(x)=\frac{x}{x^2+3x+1}\) ,题目等同于求满足 \(G(F(x))=x\)\(F\)

根据拉格朗日反演,有 \(n[x^n]F(x)=[x^{-1}]G(x)^{-n}\) 。代入得 \(n[x^n]F(x)=[x^{n-1}](x^2+3x+1)^{2n}\)

接下来有两种求法:第一种是,考虑转化成 \(\sum \tbinom{2n}{i}[x^{n-1-2i}](3x+1)^{2n-i}=\sum \tbinom{2n}{i}3^{n-1-2i}\tbinom{2n-i}{n-1-2i}\) ,\(O(n)\) 计算。

第二种是,考虑对 \(F(x)=(x^2+3x+1)^{2n}\) 求导得到 \(F'(x)=2n(x^2+3x+1)^{2n-1}(2x+3)=2n(2x+3)\frac{F(x)}{x^2+3x+1}\)

\((x^2+3x+1)F'(x)=2n(2x+3)F(x)\) 。提取两边的 \(x^k\) 项系数,得到

\((k+1)f_{k+1}+3kf_{k}+(k-1)f_{k-1}=6nf_k+4nf_{k-1}\)

\(kf_k=(6n-3k+3)f_{k-1}+(4n-k+2)f_{k-2}\) ,递推即可,复杂度 \(O(n)\)

27.ABC290Ex Bow Meow Optimization

这个题做不出来,感觉很无语。

场上先观察出来填权值是单峰的,两种数的中点所在的位置很重要,我们枚举这两个位置,然后 dp 。发现不太可做。

事实上它们的中点是贴在一起的,以 \(n,m\) 偶数为例,第 \(\frac{n}{2}\) 个猫左边的狗,如果多于 \(\frac{m}{2}\) ,我们一定可以把这些多出来的狗移到猫的右边,发现一定不劣。

然后把所有动物的权值从大到小排序,我们一定会把当前的动物放在最左或最右。依次进行 dp 即可,状态中记录左半边有多少只猫/狗。复杂度 \(O(n^3)\)

28.P5828 边双连通图计数

用双连通分量刻画普通的连通图。考虑先钦定根,观察根所在的双连通分量。

如果大小是 \(x\) ,则删掉该分量后的若干连通图,都会在 \(x\) 个点中选一个连边。

所以,如果有根连通图的 EGF 是 \(A(x)\)\(i\) 个点的边双有根连通图有 \(b_i\) 个,则 \(A(x)=\sum b_i\frac{x^i}{i!} \sum \frac{i^jA(x)^j}{j!}=\sum b_i\frac{x^i}{i!}e^{iA(x)}=\sum b_i\frac{(xe^{A(x)})^i}{i!}\)

\(b_i\) EGF 为 \(B(x)\) ,则 \(A(x)=B(xe^{A(x)})\) 。现在已知 \(A(x)\) ,如何计算 \(B(x)\) ?

考虑令 \(F(x)=xe^{A(x)}\) ,则 \(A(x)=B(F(x))\)\(A(F^{-1}(x))=B(x)\)

根据扩展拉格朗日反演,\([x^n]B(x)=[x^n]A(F^{-1}(x))=\frac{1}{n}[x^{n-1}]A'(x)(\frac{x}{F(x)})^n=\frac{1}{n}[x^{n-1}]A'(x)e^{-nA(x)}\)

直接计算即可,复杂度 \(O(n\log n)\)

29.P5827 点双连通图计数

类似地,观察根被哪些点双联通分量包含。

\(A(x)\) 表示有根连通图的EGF。你会发现除了根以外,每个点下面都挂了一个有根无向图。

如果 \(i\) 个点的点双连通图(无根)是 \(b_i\) ,令 \(B(x)=\sum\limits_{i\le 1}\frac{b_{i+1}x^i}{i!}\) ,则 \(A(x)=xe^{B(A(x))}\)

如何计算?考虑 \(ln(\frac{A(x)}{x})=B(A(x))\) 。令 \(F(x)=ln(\frac{A(x)}{x})\) ,则 \(B(A(x))=F(x)\) ,\(B(x)=F(A^{-1}(x))\)

\([x^n]B(x)=\frac{1}{n}[x^{n-1}]F'(x)(\frac{A(x)}{x})^{-n}=\frac{1}{n}[x^{n-1}]F'(x)e^{-nF(x)}\)

直接计算即可,复杂度 \(O(n\log n)\)

30.P5293 [HNOI2019]白兔之舞

如果没有 \(m\) 大小限制,考虑答案就是 \(((I+A)^L)_{x,y}\)

\(k\)\(p-1\) 因数,并且是模 \(k\)\(t\) 的形式,明示单位根反演。

\(ans_t=\frac{1}{k}\sum\limits_{i=0}^{k-1}W_{k}^{-it}(\sum\limits_{j=0}^L\tbinom{L}{j}W_{k}^{ij}A^{j})_{x,y}=\frac{1}{k}\sum\limits_{i=0}^{k-1}W_{k}^{-it}((I+AW_{k}^{i})^L)_{x,y}\)

后面这个式子只和 \(i\) 有关,可以 \(O(kn^3\log L)\) 计算。然后 \(-it=\tbinom{i}{2}+\tbinom{t}{2}-\tbinom{i+t}{2}\) ,差卷积即可得到 \(ans\) 。需要 MTT。

总复杂度 \(O(kn^3\log L+n\log n)\) 。白兔之舞,就这。

31.P4500 [ZJOI2018]树

考虑同构的一类树 \(T\) ,它的编号方法是 \(\frac{n!}{\prod a_i}\) (\(a_i\) 是以 \(i\) 为根子树的大小) ,而且一个节点 \(i\) ,如果存在 \(j\) 棵子树同构,那么还要除以 \(\prod j!\)

我们设 \(V(T)=\prod{\frac{1}{a_i}}\prod{\frac{1}{j!}}\)\(S(T)\) 是树 \(T\) 的大小,则答案是 \(\frac{(n!)^k}{(n-1)!^k}\sum [S(T)=n]V(T)^k=n^k\sum [S(T)=n]V(T)^k\)

。考虑令 \(f_i=\sum [S(T)=i]V(T)^k\) ,我们想计算出 \(f_n\)

\(f_n=\frac{1}{n^k}[x^{n-1}]\prod\limits_{T} \sum\limits_{p=0}^{+\infty}\frac{V(T)^px^{pS(T)}}{(p!)^k}\) 。经典取 ln ,\(f_n=\frac{1}{n^k}[x^{n-1}]exp(\sum\limits_{T}\ln(\sum\limits_{p=0}^{+\infty}\frac{V(T)^{pk}x^{pS(T)}}{(p!)^k}))\)

观察上面的式子,考虑令 \(H(x)=\ln(\sum\limits_{p=0}^{+\infty}\frac{x^p}{(p!)^k})\) ,则上式变成 \(f_n=\frac{1}{n^k}[x^{n-1}]exp(\sum\limits_{T}H(V(T)^kx^{S(T)}))\)

\(H(x)=\sum h_ix^i\) ,则继续化成 \(f_n=\frac{1}{n^k}[x^{n-1}]exp(\sum\limits_i h_i\sum\limits_{T}x^{S(T)i}V(T)^{ik})\)

枚举 \(S(T)\) ,化成 \(f_n=\frac{1}{n^k}[x^{n-1}]exp(\sum\limits_i h_i\sum\limits_jx^{ij}\sum\limits_{T}[S(T)=j]V(T)^{ik})\)

发现 \(\sum\limits_{T}[S(T)=j]V(T)^{ik}\)\(f_i\) 的定义非常相似,考虑对 \(f\) 添加一维,即令 \(f_{i,j}=\sum [S(T)=i]V(T)^{jk}\) ,发现这个式子就变成了 \(f_{j,k}\)

于是我们就能递推计算 \(f\) 了,算 \(f_{i,j}(j>1)\) 的方法是类似的。

认真实现可以得到复杂度 \(O(n^2\log n)\) ,就是能求前缀和/积的地方尽量求,能减少的枚举就减少。思路还是很自然的。

32.ARC157E XXYX Binary Tree

非常简单的题,但是因为提前去玩了就没仔细看,没看到二叉树的条件,寄飞了。这场思维量都很低。

考虑不存在相邻 \(Y\) 的条件很关键,相当于 \(c\) 等于非叶子的 Y 个数 *2 ,\(b\) 等于 Y 个数 -[根是Y] 。

发现如果叶子结点的 Y 数量固定,那 Y 总个数是没有下界的。

\(dp_{i,j,0/1}\) 表示以 \(i\) 为根的子树,取 \(j\) 个叶子为 Y ,Y 总个数最多是多少,然后树形 dp 转移即可。

33.ARC157F XY Ladder LCS

普通的求 LCS 是设 \(f_{i,j}\) 来转移。

于是此题的暴力就是设 \(f_{i,j,S}\) 表示第一个串考虑到 \(i\) ,第二个串考虑到 \(j\)\((\min(i,j),\max(i,j)]\) 每个位置是否交换的状态是 \(S\) ,显然过不去。

发现答案会比较大。考虑找一个答案的下界,发现长度为 \(3\) 的时候答案至少为 \(2\) ,长度为 \(2\) 时答案至少为 \(1\) 。于是长度为 \(n\) 时答案至少为 \(\left\lfloor\dfrac{2n}{3}\right\rfloor\)

所以 dp 的时候 \(|i-j|\le \left\lceil\dfrac{n}{3}\right\rceil\) 。复杂度是 \(O(2^{\frac{n}{3}}n)\)

34.ARC154F Dice Game

考虑计算丢第 \(t\) 次时刚好合法的概率:\([x^{t-1}](t-1)!\frac{n}{n}(e^{\frac{x}{n}}-1)^{n-1}=[x^t]t!x\frac{(e^{\frac{x}{n}}-1)^{n-1}}{t}\)

如果令 \(h_t=[x^t]t!x(e^{\frac{x}{n}}-1)^{n-1}\) ,则等同于要求 \(\sum h_tt^{k-1}\)

考虑计算出 \(F(x)\)\(x(e^{\frac{x}{n}}-1)^{n-1}\) 转 OGF 的结果,则 \(k+1\) 的答案是 \([x^k]k!F(e^x)\)

考虑 \(x(e^{\frac{x}{n}}-1)^{n-1}\) 转 OGF 为 \(\sum\tbinom{n-1}{i}(-1)^{n-1-i}\sum\limits_{o=0}^{+\infty}x^{o+1}(\frac{i}{n})^o\frac{(o+1)!}{o!}=\sum\tbinom{n-1}{i}(-1)^{n-1-i}\frac{x}{(1-\frac{i}{n}x)^2}\)

则通过分治 NTT ,可以把 \(F(x)\) 算成一个 \(\frac{H(x)}{G(x)}\) 的形式。

接下来我们想求 \(F(e^x)\) 的前 \(m\) 项,直接先算 \(F(x)\)\(x^m\) 处截断,再算 \(F(e^x)\) 是错的,因为 \(F\) 有无限项。

先算 \(H(e^x)\)\(G(e^x)\) ,从 \(m\) 处截断,再算 \(F(e^x)=\frac{H(e^x)}{G(e^x)}\) ,可以发现就对了。

计算一个 \(F(e^x)\) 的方式是算 \(\sum \frac{f_i}{1-ix}\) ,这也能分治 NTT。

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

35.P6633 [ZJOI2020] 抽卡

先把期望拆成:每个状态出现的概率*当前状态下抽到一张没出现的卡次数的期望 的和。其中一个状态要满足,不存在为 \(k\) 的连续段。如果状态有 \(x\) 张被抽,这个期望就是 \(\frac{n}{n-x}\) ,到达的概率显然是 \(\frac{1}{\tbinom{n}{x}}\)

则对于每个 \(x\) 都要计算取了 \(x\) 张牌的合法状态数。

我们把题目中给出的编号划分成若干连续段,分别求答案再分治 NTT 合并。

接下来考虑连续一段的答案,设其长度为 \(n\)

考虑一种容斥:我们要求 \([i,i+k-1]\) 全是 \(1\)\(i-1\)\(0\) 的情况不能出现。特别地,令 \(a_0=0\)

这样是方便计算的:令 \(G_n(x)=\sum(-1)^i\tbinom{n-ik}{i}x^{ki}(x+1)^{n-(k+1)i}\) ,则答案为 \(G_n(x)-x^kG_{n-k}(x)\)

我们令 \(f(l,r)=\sum\limits_{i=l}^r (-1)^i\tbinom{n-ik}{i}x^{k(i-l)}(x+1)^{(k+1)(r-i)}\) ,发现 \(f(l,r)=x^{(r-m)k}f(l,m)+(1+x)^{(l-m+1)(k+1)}f(m+1,r)\)

\(b=\left\lfloor\dfrac{n}{k+1}\right\rfloor\) ,则 \(G_n(x)=(x+1)^{n-(k+1)b}f(0,b)\)

于是可以分治计算,复杂度 \(O(n\log^2 n)\)

posted @ 2023-02-06 20:22  grass8woc  阅读(300)  评论(3编辑  收藏  举报