P9745

感觉是那种,看到题就能猜到大概思路的题。

首先给题目条件增加限制:考虑 xi7 的时候怎么做。这启示我们思考一个和值域相关的做法。

很容易想到一个树形 dp:设 dpu,i 为在以 i 为根的子树中,u 所在连通块异或和为 i 时方案数与其他连通块各自的异或和之积的乘积。则有:

dpu,ij+dpu,i×dpv,jdpu,ij

dpu,i×dpv,j×jdpu,i

以树上背包的形式合并。

以上做法能得到 36pts。考虑怎样拓展至值域更大的情况。

异或具有很好的性质。可以考虑拆开每一位分别算。状态变为 dpu,i,0/1 表示在以 i 为根的子树中,u 所在连通块异或和的第 i 位为 0/1 时方案数与其他连通块各自的异或和之积的乘积。

再来分析两种转移:第一种没太大变化,向两个数当前位的异或值转移。第二种则有一点变化。可以考虑乘法分配律暴力拆开,发现每个为 1 的位都会对当前位的 dp 值有贡献。所以便变成:

dpu,i,pq+dpu,i,p×dpv,i,qdpu,i,pq

dpu,i,p×dpv,j,1×2jdpu,i,p

这样就有 84pts 了。最后一个转移是 O(log2V) 的,发现可以再用分配律合起来,就变成 O(logV) 的了。总复杂度 O(nlogV)

点击查看代码
int n,m,dp[N][64][2],f[64][2];
ll c[N];
int tot,head[N];
struct node{
	int to,nxt;
}e[N<<1];
il void add(int u,int v){
	e[++tot]={v,head[u]};
	head[u]=tot;
}
il int Mod(int x,int y){
	((x+=y)>=mod)&&(x-=mod);
	return x;
}
void dfs(int u,int fa){
	rep(i,0,62){
		dp[u][i][(c[u]>>i)&1ll]=1;
	}
	go(i,u){
		int v=e[i].to;
		if(v==fa)
			continue;
		dfs(v,u);
		int sum=0;
		rep(j,0,62){
			sum=Mod(sum,1ll*dp[v][j][1]*((1ll<<j)%mod)%mod);
		}
		mems(f,0);
		rep(j,0,62){
			rep(p,0,1){
				rep(q,0,1){
					f[j][p^q]=Mod(f[j][p^q],1ll*dp[u][j][p]*dp[v][j][q]%mod);
				}
				f[j][p]=Mod(f[j][p],1ll*dp[u][j][p]*sum%mod);
			}
		}
		rep(j,0,62)rep(k,0,1){
			dp[u][j][k]=f[j][k];
		}
	}
}
void Yorushika(){
	scanf("%d",&n);
	rep(i,1,n){scanf("%lld",&c[i]);}
	rep(i,2,n){
		int v;scanf("%d",&v);
		add(v,i),add(i,v);
	}
	dfs(1,0);
	int ans=0;
	rep(i,0,62){ans=Mod(ans,1ll*dp[1][i][1]*((1ll<<i)%mod)%mod);}
	printf("%d\n",ans);
}
signed main(){
	int t=1;
	//	scanf("%d",&t);
	while(t--)
		Yorushika();
}
posted @   yinhee  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示