列表

详情


NC200547. 划分树

描述

给出一棵 n 个点的树,点编号 1..n , i 号点的点权是 a_i 。
可以通过删边的方式将这棵树划分成一些连通块,求有多少种不同的划分方案,满足:划分后每个连通块的点权异或和均为 M 。
答案对  取模。

输入描述

第一行两个整数 n, M 。
第二行 n-1 个整数,第 i 个数表示 i+1 号点的父亲编号。
第三行 n 个整数,第 i 个表示 i 号点的点权。
保证  。
保证输入构成一棵树。

输出描述

输出一行一个整数,表示符合条件的划分方案数对  取模的结果。

示例1

输入:

3 0
1 1
0 0 0

输出:

4

说明:

\emptyset, \{2\}, \{3\}, \{2,3\}
集合内的元素表示删掉它与父亲之间的边.(以 1 号点为根)

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 388ms, 内存消耗: 16224K, 提交时间: 2020-03-17 13:52:33

#include <bits/stdc++.h>
using namespace std;
 
const int N = 500003, mod = 1004535809;
typedef long long ll;
ll dp[N][2];
struct Edge {
  int v, nxt;
} G[N]; int head[N], a[N], M;
void adde(int u, int v) {
  G[++head[0]] = (Edge) {v, head[u]}; head[u] = head[0];
}
void dfs(int u) {
  dp[u][0] = 1;
  ll dpu0, dpu1;
  for (int i = head[u]; i; i = G[i].nxt) {
    int v = G[i].v;
    dfs(v);
    a[u] ^= a[v];
    dpu0 = dp[u][0], dpu1 = dp[u][1];
    dp[u][0] = (dpu0 * dp[v][0] + dpu1 * dp[v][1]) % mod;
    dp[u][1] = (dpu0 * dp[v][1] + dpu1 * dp[v][0]) % mod;
  }
  dpu0 = dp[u][0], dpu1 = dp[u][1];
  if (u == 1) cout << (dpu0 * (a[u] == M) + dpu1 * (a[u] == 0)) % mod;
  //和父亲的边
  if (a[u] == 0) (dp[u][0] += dpu1) %= mod;
  if (a[u] == M) (dp[u][1] += dpu0) %= mod;
}
int main() {
  int n;
  scanf("%d%d", &n, &M);
  for (int u, i = 2; i <= n; i++) scanf("%d", &u), adde(u, i);
  for (int i = 1; i <= n; ++i) scanf("%d", a + i);
  dfs(1);
  return 0;
}

C++(clang++ 11.0.1) 解法, 执行用时: 379ms, 内存消耗: 33984K, 提交时间: 2023-07-29 23:54:57

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define PII pair<int,int>
const int N=5e5+5,mod=1004535809;int n,m;
vector<int>son[N];
ll a[N],f[N][2];ll ans=0;
void dfs(int u){	
	f[u][0]=1;
	for(auto v:son[u]){
		dfs(v);
		a[u]^=a[v];
		ll f0=f[u][0],f1=f[u][1];
		f[u][1]=(f1*f[v][0]+f0*f[v][1])%mod;
		f[u][0]=(f0*f[v][0]+f1*f[v][1])%mod;
	}
	ll f1=f[u][1],f0=f[u][0];
	if(u==1)ans=(ans+f0*(a[u]==m))+f1*(a[u]==0);
	if(a[u]==m)f[u][1]=(f[u][1]+f0)%mod;
	if(a[u]==0)f[u][0]=(f[u][0]+f1)%mod;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=2;i<=n;i++){
		int fa;
		scanf("%d",&fa);
		son[fa].push_back(i);
	}
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	dfs(1);
	printf("%d\n",ans%mod);
} 

上一题