纪念灾难

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

\[2^k×2^{n-all+1}×(\sum_{i=2}^{cnt}\binom{cnt}{i}[i\%2=1]×2^{all-cnt}+cnt×(2^{all-cnt}-1))(u!=1) \]

\[2^k×2^{n-all}×(\sum_{i=1}^{cnt}\binom{cnt}{i}[i\%2=0]×2^{all-cnt-1}+2^{all-cnt-1}-1)(u=1,f[k]=1) \]

\[2^k×2^{n-all}×2^{all-cnt-1}×(\sum_{i=1}^{cnt}\binom{cnt}{i}[i\%2=1])(u=1,f[k]=0) \]

化简后贡献为三个式子:

\[2^{n+k-2}-cnt×2^{n+k-all-1}(u!=1) \]

\[2^{n+k-all}×(2^{all-2}-1)(u=1,f[k]=1) \]

\[2^{n+k-2}(u=1,f[k]=0) \]

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

\[2^{n+i-all}×(2^{all-1}-1)(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 @ 2024-09-27 19:42  SLS-wwppcc  阅读(38)  评论(0)    收藏  举报