#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;
}
是一种偏暴力的做法,根据枚举的数值的二进制判断删除哪些边,然后再对应答案异或到数组里