2月杂题

1.P3920 [WC2014]紫荆花之恋

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

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

2.CF1063F String Journey

O(nn) :观察到答案不超过 n ,暴力即可。

O(nlogn) :考虑 dpi 表示 [i,n] 这个串的答案,则 dpidpi+1+1

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

相当于要找到一个 j 使得 ji+x,dpjx1,max(lcp(i,j),lcp(i+1,j))x1

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

3.P4649 [IOI2007] training 训练路径

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

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

dpx,i 表示处理了子树 xxfa 染色为 i ,最大的权值。我们对于每个路径,在 lca 处算贡献。

转移是一个状压 dp 的过程,复杂度 O(210(n+m)+nm)

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

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

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

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

由此扫描线即可。复杂度 O(nlogn)

5.P6846 [CEOI2019] Amusement Park

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

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

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

fS 是子集 S 的答案,gS[S](1)|S|1 ,则 fS=TSgTfST

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

6.CF1787H Codeforces Scoreboard

先化成 max(0,bikit) 的形式。我们可以看成每个式子在 0bikit 中选一个。

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

所以把全局的式子排序,令 dpi,j 表示考虑前 i 个,选了 j 个的最大权值,则 dpi,j=max(dpi1,j1+bikij,dpi1,j) 。令 zi,j=dpi,jdpi,j1

考虑转移,一开始猜测 dpi 是上凸的,即 zi,jzi,j+1 。然后维护差分数组。其实是对的,但是不好证明。

根据证明中的障碍,进一步猜测 zi,jzi,j+1ki ,这反而更好证明,且更好利用。证明如下:

考虑归纳证明,假设 z1zi1 都是满足条件的。

考虑转移的过程, max 式子中的两个值,作差法得到 bikijzi1,jj 变成 j+1 ,前面这个式子的增加量就是 zi1,jzi1,j+1kiki1ki0 。所以这个式子是单调不减的。

ki1ki0 是因为我们已经从大到小排序了。

我们令 x 是第一个满足 bikijzi1,j0jf 变化时 z 的变化:相当于 zi,j=zi1,j(1j<x)zi,x=bikix ,zi,j=zi1,j1ki(j>x) 。(如果不想看证明,即可用平衡树维护这个过程。)

对于 jx2zi,jzi,j+1=zi1,jzi1,j+1ki1ki 。对于 j=x1zi,jzi,j+1=zi1,x1(bikix)

因为对于 j<x ,都有 bikijzi1,j<0 ,则 bikix+kizi1,x1<0zi1,x1bi+kix>ki

对于 j=xzi,jzi,j+1=(bikix)zi1,x+1 。同 j=x1 的证明,可以得到这是 ki 的。

对于 j>x ,同 jx2 的证明,zi,jzi,j+1=(zi1,j1ki)(zi1,jki)=zi1,j1zi1,jki1ki

综上,对于任意 j>0 ,有 zi,jzi,j+1ki ,结论成立。

7.ABC288Ex A Nameless Counting Problem

我们计算 fi 表示 i 个互不相同的数的答案,则之后同时插入两个数,答案为 fn2i(m+ii)

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

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

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

再算一个 hi 表示任意 i 个数的答案。则 fi=1i!gi,jhj

h 直接数位 dp,复杂度是 O(n3logm)

8.CF1787I Treasure Hunt

神题

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

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

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

i>mid 时,令 ai 表示 j(mid+1,i] 的最大的 sjbi 表示 (mid+1,i] 的最大子段和。

imid 时,定义类似。

则问题转化为计算 max{ai+aj,bi,bj} ,这是二维偏序问题,可以 O(nlogn) 计算,则总复杂度为 O(nlog2n)

有结论:aibi(i>mid) 是单调不降的,aibi(imid) 是单调不增的。利用这个就能维护三个指针,进行计算了,复杂度 O(nlogn)

给出 i>mid 时的证明:

令考虑到 i 时,最大字段和是 srsl,最大前缀和是 sq 。则根据本文一开始的讨论,r=ql>q

如果 r=q ,则加入 i+1Δa=Δb=max(si+1sq,0)

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

  1. q 将变成 i+1Δa=si+1sq。发现 Δbsi+1srsi+1sq=Δa

  2. q 不变,则 Δa0Δb=0

就证完了 ΔaΔb

9.CF1785E Infinite Game

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

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

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

这样做是 O(n2) ,常数 44242=213 。跑不满,跑满了也能过(

10.P7985 [USACO21DEC] Paired Up P

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

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

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

fi,j,k,l,其中 k 表示第一类牛最后一个没考虑的,l 同理。

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

现在就变成 fi,j,k 了。考虑何时 k 能变成另一类牛?

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

于是状态就简化成 fi,j,0/1 了,O(n2) 可通过本题。

11.ABC215H Cabbage Master

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

fS 是左端点集合 S ,使并集 TS 的情况下的最大的 b

gSS 集合的 a,则第一问答案是 an=minfSgS+1 ,其中 fS0

考虑第二问,我们删去 an 个小球后,令这些小球覆盖的左端点集合为 T ,则一定存在 TS 使得 fSgS+1=an

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

12.ABC289Ex Trio

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

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

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

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

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

神题。

专门开了一篇写做法。

自己没想到的东西:

  1. 拆模数,求模数为 pici 的答案后 CRT 合并。这是很常见的方法。

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

14.「WC2023 / CTS2023」楼梯

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

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

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

考虑查询。发现一个子楼梯对应了一个子段 [l,r] ,满足 al=0,ar=1 ,且 rl 就是边界格数。

现在查询相当于要取一对 l,r 使得 al=0,ar=1,rl=q

由题,a0=0,an=1 ,且 nq 倍数。那么考虑二分,初始 l=0,r=n/q 。如果 aqmid1 ,就令 r:=mid ,否则 l:=mid

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

复杂度 O(nlog2n)

15.AGC061C First Come First Serve

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

简化题意:有两个长度为 n 的单调递增序列 lr ,并且不存在 li=rj 。你可以使 ai 等于 li 或者 ri

一个排列 ppi 表示 a 中第 i 小的数的下标。问有多少种不同的 p1n5105

做法:

考虑对于 p ,怎么构造出 a。可以从左往右贪心构造:如果 api1<lpi ,则 api=lpi ,否则 api=rpi

而一组 a 只会对应一个 p 。则一组 a 会在它对应的 p 的构造中被“采用”,当且仅当:如果存在 i 使 ai=ri ,则必须存在 aj 使得 li<aj<ri

由此,考虑容斥处理这个限制。钦定一些 i ,使得 ai=ri ,且不存在 j 使 li<aj<ri 。 我们称这个限制为,[li,ri] 都被 i 覆盖了。

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

其次,如果有一个 j ,两端都被覆盖了,则对答案贡献为 0 ;否则,贡献为 2nrili

如果 j 两端都被覆盖,由于 lr 单调递增,一定是相邻两个钦定了的区间 i1,i2,使得 i1<j<i2,lj<ri1,rj>li2

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

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

16.CF765F Souvenirs

考虑把询问按右端点排序,然后加入 ai 时,我们先考虑 ajai 的数对。

如果已经取到一个 ajai ,则对于 k<j ,必须满足 akaj>aiak ,这个 (k,i) 才对答案的更新有用。

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

复杂度 O(nlog2n)

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

FWT 练习题。

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

我们来回忆一下FWT:aS=(1)o(S,T)aT 。以及 IFWT, NaS=(1)o(S,T)aT

把题意写成集合幂级数的形式: [x0]{1+2xpi}

1+2xpi 施加 FWT 得到 Fi(x) ,考虑 [xS]Fi(x) ,如果 o(S,pi) 为奇数,则为 1 ,否则为 3

那我们对于每个 S ,我们想算 [xS]Fi(x) ,只需统计出 (1)o(S,pi) 即可。这恰好能用 FWT 计算。

而答案恰好是 [xS]Fi(x) ,因为 o(0,S)=0

18.CF1672I PermutationForces

神题,难想难写。

ci 初始为 |ipi| 。我们令第 i 个点是 (i,pi)

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

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

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

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

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

细节很多。我写得很烦。

代码(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 个点的无标号有根树方案 fn ,无标号无根树方案为 gn 。如果已经计算出 fi ,我们考虑拎出重心,得到 gn=fn2j>nfjfnj 。特别地,如果 n 为偶数,还要减去 (fn/22)

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

F(x)=fixi 。一个大小为 k 的环,这个环代表的 k 个树都要相同,然后内部连边方案 (k1)! ,则它的 EGF 为 F(xk)(k1)!k!=F(xk)k

把他们拼起来,则 fi=[xi1]eF(xk)k 。(注意这里 EGF 的 n! 和求平均数的 1n! 抵消了).

即:F(x)=xeF(xk)k 。我们令 E(x)=F(xk)kF(x)=xeE(x)

考虑两边求导: F(x)=eE(x)+xeE(x)E(x)

xF(x)F(x)=xE(x)F(x)。而 xE(x) 可以展开为 j1i1xijfjj

不难发现可以分治 FFT 解决:令 gi=d|ifd ,则 f1=1fi=1i1j=1i1fjgij(i>1)

复杂度 O(nlog2n)

19.ABC230H Bullion

和上面这个题类似,令 A(x)=exp(aSxaa)S 是题中给出的金条体积的集合)(这里需要 exp)。

答案生成函数为 F(x)E(x)=F(xk)k ,则 F(x)=x(eE(x)A(x)1)

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

复杂度 O(nlog2n)

20.ARC156D Xor Sum 5

考虑最后会贡献给答案的,肯定是 [xs](xai)k 为奇数的 s

然后你发现,(xai)2 在模 2 时得到 x2ai

那我们将 k 二进制拆分,就得到 pk(xai2p) 。由此可以从低到高数位 dp 。

21.ARC156E Non-Adjacent Matching

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

首先度数和 S 一定是偶数;其次考虑相邻两个不能连边能得到什么,卡一些极端情况试试,想到 xi+xi+1S2

发现这个确实是充分的,考虑 bi=S2xixi+1 ,则连边 (u,v) 等同于除了 bu,bu+1,bv,bv+1 这四个数都要减 1 ,最后 b 要变成全 0

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

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

然后计数就是容斥钦定一些位置 bi+bi+1>S2 ,则要么钦定一处,要么钦定两处且相邻。

就容易算了,复杂度 O(n2+k)

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

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

令每个环的大小分别为 x1,x2,,xk ,则令 A=xi2+i=1kj=i+1kgcd(xi,xj) ,则不动点为 mA

枚举 p 不现实,考虑枚举 n 的划分 x,填位置系数 1xi! ,内部连环系数 (xi1)! ,则对答案贡献为 A(x)n!xi

注意到相等的 x 是会算重的,如果 ix 出现 ci 次,则还要乘上 1ci!

最后除以 n!

复杂度 O(P(n)n2)

23.CF1784F Minimums or Medians

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

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

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

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

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

24.AGC061D Almost Multiplication Table

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

先二分答案,得出 xiyj 的上下界。

考虑把 x 设为 xi=i ,这一定是严格最小的 x :如果存在合法解 x,一定有 xixi

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

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

考虑如何保证复杂度:我们钦定 xnym ,如果 xn>ym 就退出调整,再对称的做一遍 ymxn

这样的话,由于 xnymai,j+k ,所以 xn 只会到达 O(V) 的级别。

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

算上二分和每次调整的复杂度,总复杂度 O(n3VlogV)

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

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

考虑这个根,它会被一些边和环覆盖。 如果它在一个环上,则环上面另外 i1 个点分别挂了一颗仙人掌(此处体现了有根的作用)的 EGF 是 12i2Fi(x)

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

我们会把环和边叠起来,所以得到 F(x)=xexp(12i2Fi(x)+F(x))=xexp(2F(x)F(x)222F(x))

我们来牛顿迭代,令 G(F(x))=xexp(12i2Fi(x)+F(x))=xexp(2F(x)F(x)222F(x))F(x)

t=F0(x)P(t)=xexp(2tt222t) ,可以得到 F(x)=tP(t)tP(t)t22t+22t24t+21

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

26.ABC222H Beautiful Binary Tree

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

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

考虑 fi,0/1 ,分别表示根为 0/1 的答案。把它写成生成函数的形式:F0,F1 ,则有 F0=(F1+1)21 (-1是因为叶子节点必须是 1),F1=x(F0+F1+1)2

x=F1(x)(1+3F1(x)+F1(x)2)2 。令 G(x)=xx2+3x+1 ,题目等同于求满足 G(F(x))=xF

根据拉格朗日反演,有 n[xn]F(x)=[x1]G(x)n 。代入得 n[xn]F(x)=[xn1](x2+3x+1)2n

接下来有两种求法:第一种是,考虑转化成 (2ni)[xn12i](3x+1)2ni=(2ni)3n12i(2nin12i) ,O(n) 计算。

第二种是,考虑对 F(x)=(x2+3x+1)2n 求导得到 F(x)=2n(x2+3x+1)2n1(2x+3)=2n(2x+3)F(x)x2+3x+1

(x2+3x+1)F(x)=2n(2x+3)F(x) 。提取两边的 xk 项系数,得到

(k+1)fk+1+3kfk+(k1)fk1=6nfk+4nfk1

kfk=(6n3k+3)fk1+(4nk+2)fk2 ,递推即可,复杂度 O(n)

27.ABC290Ex Bow Meow Optimization

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

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

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

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

28.P5828 边双连通图计数

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

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

所以,如果有根连通图的 EGF 是 A(x)i 个点的边双有根连通图有 bi 个,则 A(x)=bixii!ijA(x)jj!=bixii!eiA(x)=bi(xeA(x))ii!

bi EGF 为 B(x) ,则 A(x)=B(xeA(x)) 。现在已知 A(x) ,如何计算 B(x) ?

考虑令 F(x)=xeA(x) ,则 A(x)=B(F(x))A(F1(x))=B(x)

根据扩展拉格朗日反演,[xn]B(x)=[xn]A(F1(x))=1n[xn1]A(x)(xF(x))n=1n[xn1]A(x)enA(x)

直接计算即可,复杂度 O(nlogn)

29.P5827 点双连通图计数

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

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

如果 i 个点的点双连通图(无根)是 bi ,令 B(x)=i1bi+1xii! ,则 A(x)=xeB(A(x))

如何计算?考虑 ln(A(x)x)=B(A(x)) 。令 F(x)=ln(A(x)x) ,则 B(A(x))=F(x) ,B(x)=F(A1(x))

[xn]B(x)=1n[xn1]F(x)(A(x)x)n=1n[xn1]F(x)enF(x)

直接计算即可,复杂度 O(nlogn)

30.P5293 [HNOI2019]白兔之舞

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

kp1 因数,并且是模 kt 的形式,明示单位根反演。

anst=1ki=0k1Wkit(j=0L(Lj)WkijAj)x,y=1ki=0k1Wkit((I+AWki)L)x,y

后面这个式子只和 i 有关,可以 O(kn3logL) 计算。然后 it=(i2)+(t2)(i+t2) ,差卷积即可得到 ans 。需要 MTT。

总复杂度 O(kn3logL+nlogn) 。白兔之舞,就这。

31.P4500 [ZJOI2018]树

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

我们设 V(T)=1ai1j!S(T) 是树 T 的大小,则答案是 (n!)k(n1)!k[S(T)=n]V(T)k=nk[S(T)=n]V(T)k

。考虑令 fi=[S(T)=i]V(T)k ,我们想计算出 fn

fn=1nk[xn1]Tp=0+V(T)pxpS(T)(p!)k 。经典取 ln ,fn=1nk[xn1]exp(Tln(p=0+V(T)pkxpS(T)(p!)k))

观察上面的式子,考虑令 H(x)=ln(p=0+xp(p!)k) ,则上式变成 fn=1nk[xn1]exp(TH(V(T)kxS(T)))

H(x)=hixi ,则继续化成 fn=1nk[xn1]exp(ihiTxS(T)iV(T)ik)

枚举 S(T) ,化成 fn=1nk[xn1]exp(ihijxijT[S(T)=j]V(T)ik)

发现 T[S(T)=j]V(T)ikfi 的定义非常相似,考虑对 f 添加一维,即令 fi,j=[S(T)=i]V(T)jk ,发现这个式子就变成了 fj,k

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

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

32.ARC157E XXYX Binary Tree

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

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

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

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

33.ARC157F XY Ladder LCS

普通的求 LCS 是设 fi,j 来转移。

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

发现答案会比较大。考虑找一个答案的下界,发现长度为 3 的时候答案至少为 2 ,长度为 2 时答案至少为 1 。于是长度为 n 时答案至少为 2n3

所以 dp 的时候 |ij|n3 。复杂度是 O(2n3n)

34.ARC154F Dice Game

考虑计算丢第 t 次时刚好合法的概率:[xt1](t1)!nn(exn1)n1=[xt]t!x(exn1)n1t

如果令 ht=[xt]t!x(exn1)n1 ,则等同于要求 httk1

考虑计算出 F(x)x(exn1)n1 转 OGF 的结果,则 k+1 的答案是 [xk]k!F(ex)

考虑 x(exn1)n1 转 OGF 为 (n1i)(1)n1io=0+xo+1(in)o(o+1)!o!=(n1i)(1)n1ix(1inx)2

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

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

先算 H(ex)G(ex) ,从 m 处截断,再算 F(ex)=H(ex)G(ex) ,可以发现就对了。

计算一个 F(ex) 的方式是算 fi1ix ,这也能分治 NTT。

复杂度 O(nlog2n)

35.P6633 [ZJOI2020] 抽卡

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

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

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

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

考虑一种容斥:我们要求 [i,i+k1] 全是 1i10 的情况不能出现。特别地,令 a0=0

这样是方便计算的:令 Gn(x)=(1)i(niki)xki(x+1)n(k+1)i ,则答案为 Gn(x)xkGnk(x)

我们令 f(l,r)=i=lr(1)i(niki)xk(il)(x+1)(k+1)(ri) ,发现 f(l,r)=x(rm)kf(l,m)+(1+x)(lm+1)(k+1)f(m+1,r)

b=nk+1 ,则 Gn(x)=(x+1)n(k+1)bf(0,b)

于是可以分治计算,复杂度 O(nlog2n)

posted @   grass8woc  阅读(353)  评论(3编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示