专栏文章

[AGC047D] Twin Binary Trees 题解

AT_agc047_d题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minjuaix
此快照首次捕获于
2025/12/02 03:35
3 个月前
此快照最后确认于
2025/12/02 03:35
3 个月前
查看原文
观察到答案可以表示为:其中 viv_i 表示 ii 到根编号的乘积。
ijvi×vj×vpi×vpjvlca(i,j)×vfa_lca(i,j)×vlca(pi,pj)×vfa_lca(pi,pj)\sum_{i}\sum_j \frac{v_i\times v_j\times v_{p_i}\times v_{p_j}}{v_{lca(i,j)}\times v_{fa\_lca(i,j)}\times v_{lca(p_i,p_j)}\times v_{fa\_lca(p_i,p_j)}}
显然可以 dfs 枚举 lca(i,j)lca(i,j),此时 i,ji,j 分处于两棵子树。然后考虑 pi,pjp_i,p_j 的贡献。
考虑 pip_i 放在原地,然后从 pjp_j 向上遍历,不难发现每次只需要计算一棵子树内的 pip_i 的贡献和,发现 pip_i 也可以先向上遍历,并在经过的点上打上标记。
时间复杂度 O(nlog2n)O(n\log^2 n)
C
#define mo 1000000007
int ksm(int x,int y)
{
	int ans=1;
	while(y)
	{
		if(y&1)ans=1ll*ans*x%mo;
		x=1ll*x*x%mo,y>>=1;
	}return ans;
}
#define inc(x,y) (x+=y,x-=x>=mo?mo:0)
#define dec(x,y) (x-=y,x+=x<0?mo:0)
const int N=4e5+5;
int n,m,o,a[N],v[N],iv[N],ans,f[N],vv[N];
#define mid ((l+r)>>1)
void dfs(int x,int l,int r)
{
	if(l==r)return;
	dfs(x<<1,l,mid),dfs(x<<1|1,mid+1,r);
	fo(i,l,mid)
	{
		for(rg j=a[i];j;j>>=1)inc(f[j],vv[i]);
	}
	int s=0;
	fo(i,mid+1,r)
	{
		for(rg k=a[i],j=a[i]>>1;j;j>>=1,k>>=1)inc(s,1ll*f[k^1]*vv[i]%mo*iv[j]%mo*iv[j>>1]%mo);
	}
	inc(ans,1ll*s*iv[x]%mo*iv[x>>1]%mo);
	fo(i,l,mid)
	{
		for(rg j=a[i];j;j>>=1)f[j]=0;
	}
}
int main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>m,n=(1<<m)-1,o=(1<<m>>1)-1,m=o+1;
	fo(i,o+1,o+m)cin>>a[i],a[i]+=o;
	v[0]=1,iv[0]=1;
	fo(i,1,n)
	{
		v[i]=1;
		for(rg j=i;j;j>>=1)v[i]=1ll*v[i]*j%mo;
		iv[i]=ksm(v[i],mo-2);
	}
	fo(i,o+1,o+m)vv[i]=1ll*v[i]*v[a[i]]%mo;
	dfs(1,o+1,o+m);
	cout<<ans;
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...