纪念灾难

一些时候,我们需要更细致一些。
在我们把答案式子成功推出,并且注意到了所有的统计答案细节之后。
遇到在小样例上全过,但是大样例GG的情况时,要注意一些预处理的量是否正确。
比如一些次幂项,是否会有部分调用越界,否则容易浪费时间。
这道题
答案稍微想一想就可以转化,然后开始想式子。
初始三个统计式子(枚举2进制第k位,all是子树大小,cnt是该位上有几个点为1):
ps:cnt在非根处统计父节点,根处不统计。

2k×2nall+1×(i=2cnt(cnti)[i%2=1]×2allcnt+cnt×(2allcnt1))(u!=1)

2k×2nall×(i=1cnt(cnti)[i%2=0]×2allcnt1+2allcnt11)(u=1,f[k]=1)

2k×2nall×2allcnt1×(i=1cnt(cnti)[i%2=1])(u=1,f[k]=0)

化简后贡献为三个式子:

2n+k2cnt×2n+kall1(u!=1)

2n+kall×(2all21)(u=1,f[k]=1)

2n+k2(u=1,f[k]=0)

考试结束,没事,接着打。
打出来交上去,全WA,于是狂调不止。
注意到第二种情况对应代码里面我们少减了1。
打出来交上去,全WA,于是狂调不止。
然后我们成功的发现了一处问题,第二个式子,由于我们是根据二项式定理得来的,发现在cnt=0时它有问题。
所以在cnt=0时变为:

2n+iall×(2all11)(u=1,f[i]=1)

打出来交上去,全WA,于是狂调不止。
经过两个小时的折磨,我们成功精神崩溃,然后去找同志们核对式子。
核对了一圈发现自己完全正确,于是回来狂调不止,最后在对拍下发现奇妙现象,在值域小于等于4时全部正确。
这时才发现,我们前面合并了多个2的次幂,最终式子承受不了只在2的n次之内的预处理。
打出来交上去,AC。
...再细致点吧。

#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
#define qr qr()
#define ps push_back
#define pa pair<int,int>
#define ve vector
#define fi first
#define se second
using namespace std;
const int N=1e5+400,mod=1e9+7;
const ll INF=0x7fffffffffffffff;
int n,tot,h[N],a[N],cnt[N][31],all[N];
ll ans,p[N*2];
inline int qr{
	int x=0;char ch=getchar();
	while(ch>57||ch<48)ch=getchar();
	while(ch>=48&&ch<=57)x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x;
}
struct node{
	int t,nx;
}e[N];
inline void add(int f,int t){
	e[++tot]={t,h[f]};h[f]=tot;
}
bool f[32];
void dfs(int u){
	all[u]=1;
	if(u!=1){
		for(int i=0;i<=30;++i){
			if((a[u]>>i)&1)++cnt[u][i];
		}
	}else for(int i=0;i<=30;++i)if((a[u]>>i)&1)f[i]=1;
	for(int i=h[u];i;i=e[i].nx){
		int v=e[i].t;
		dfs(v);
		for(int i=0;i<=30;++i){
			if((a[v]>>i)&1)++cnt[u][i];
		}++all[u];
	}
	if(!all[u])return;
	if(u!=1){
		for(int i=0;i<=30;++i){
			int k=cnt[u][i];
			if(!k)continue;
			ans=(ans+p[n+i-2])%mod;
			ans=(ans-k*p[n+i-all[u]-1]%mod+mod)%mod;
			// ans=(ans+p[n+i-k-2]*((p[k]-2*k+mod)%mod)%mod)%mod;
			// ans=(ans+p[n+i-all[u]-1]*k%mod*(p[all[u]-k]-1))%mod;
		}
	}
	else{
		for(int i=0;i<=30;++i){
			int k=cnt[u][i];
			if(!k&&!f[i])continue;
			// cout<<all[u]<<' '<<cnt[u][i]<<' '<<f[i]<<' '<<i<<endl;
			if(f[i]&&cnt[u][i]>0)ans=(ans+p[n+i-all[u]]*(p[all[u]-2]-1))%mod;
			else if(f[i])ans=(ans+p[n+i-all[u]]*(p[all[u]-1]-1))%mod;
			else ans=(ans+p[n+i-2])%mod;
		}
	}
}
void init(){
	n=qr;
	p[0]=1;
	for(int i=1;i<=N;++i)p[i]=p[i-1]*2%mod;
	for(int i=1;i<=n;++i)a[i]=qr;
	for(int i=1,f;i<n;++i)f=qr,add(f,i+1);
	dfs(1);cout<<ans;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);



	freopen("climb.in","r",stdin);freopen("climb.out","w",stdout);



	init();
	return 0;
}
posted @   SLS-wwppcc  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示