样例1过2不过数值偏大求助
查看原帖
样例1过2不过数值偏大求助
982032
XRJprogram楼主2023/10/16 05:54
#include <iostream>
#include <string.h>
#define mod 998244353;
using namespace std;
const int maxn=1e5+10;
int fa[maxn],de[maxn],newfa[maxn],answ[maxn];
int n;
long long value[maxn];
int fin(int fx){
	if(fa[fx]==fx)return fx;
	return fa[fx]=fin(fa[fx]);
}
int newfin(int fx){
	if(newfa[fx]==fx)return fx;
	return newfa[fx]=newfin(newfa[fx]);
}
bool all0(){
	for(int i=1;i<=n;i++){
		if(answ[i])return false;
	}return true;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++)cin>>value[i];
	for(int i=1;i<=n;i++)fa[i]=i;
	for(int i=2,inp;i<=n;i++){
		cin>>inp;
		fa[i]=fin(inp);
	}long long result,total=0;
	//for(int i=1;i<=n;i++)cout<<fa[i];
	for(int i=0;i<=((1<<(n-1))-1);i++){
		for(int j=1;j<=n;j++)newfa[j]=fa[j];
		for(int j=2;j<=n;j++)if((int)(i/(1<<(j-2)))%2==1)newfa[j]=j;//根据枚举的数序号判断删除哪些边 
		for(int j=2;j<=n;j++)newfa[j]=newfin(j);//重新并查集
		memset(answ,0,sizeof(answ));//
		for(int j=1;j<=n;j++)answ[newfa[j]]^=value[j];//父亲一样的节点权值放入answ里 
		result=1;//cout<<answ[1]<<answ[2]<<answ[3]<<endl; 
		for(int j=1;j<=n;j++)result*=(answ[j]==0?1:answ[j]);
		if(all0())result=0;//特判-全是0
		total+=result%mod;
		//cout<<result<<endl; 
	}
	cout<<total%mod;
}

是一种偏暴力的做法,根据枚举的数值的二进制判断删除哪些边,然后再对应答案异或到数组里

2023/10/16 05:54
加载中...