题目链接:点击打开链接
题意:
给定n个点的树
问:
对于以i为根时,把树边黑白染色,使得任意点走到根的路径上不超过一条黑边,输出染色的方案数(mod 1e9+7)
思路:
显然i点的方案数 = i为根的子树的方案数 * 不包括i为根的子树的部分的方案数
首先以i为根的子树求一个方案数down[i]:for all son vj of i, down[i] = multiply down[j]
求不包括i子树的时候为了避免除法,对儿子的方案数求一个前缀积和后缀积即可
避免了使用逆元
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <vector>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
const double eps = 1e-8;
const double pi = acos(-1.0);
template <class T>
inline bool rd(T &ret) {
char c; int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c<'0' || c>'9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
template <class T>
inline void pt(T x) {
if (x <0) { putchar('-'); x = -x; }
if (x>9) pt(x / 10);
putchar(x % 10 + '0');
}
using namespace std;
typedef long long ll;
const int N = 200100;
const int mod = 1e9 + 7;
int n;
vector<int>G[N];
vector<ll>D[N], P[N];
ll down[N], up[N];
ll go[N];
void mul(ll &x, ll y){
x *= y;
x %= mod;
}
void dfs_down(int u, int fa){
down[u] = 1;
for (int i = 0; i < G[u].size(); i++){
int v = G[u][i]; if (v == fa){
D[u].push_back(1); P[u].push_back(1); continue;
}
dfs_down(v, u);
mul(down[u], down[v] + 1);
D[u].push_back(down[v] + 1);
P[u].push_back(down[v] + 1);
}
for (int i = 1; i < D[u].size(); i++) mul(D[u][i], D[u][i - 1]);
for (int i = (int)P[u].size() - 2; i >= 0; i--)
mul(P[u][i], P[u][i + 1]);
}
void dfs_up(int u, int fa, ll way){
up[u] = way;
for (int i = 0; i < G[u].size(); i++){
int v = G[u][i]; if (v == fa)continue;
ll tmp = way;
if (i && i < (int)D[u].size()) mul(tmp, D[u][i - 1]);
if (i + 1 < P[u].size())
mul(tmp, P[u][i + 1]);
dfs_up(v, u, tmp + 1);
}
}
int main(){
rd(n);
for (int i = 2, x; i <= n; i++){
rd(x); G[x].push_back(i); G[i].push_back(x);
}
dfs_down(1, 1);
dfs_up(1, 1, 1);
for (int i = 1; i <= n; i++)pt(down[i] * up[i] % mod), putchar(' ');
return 0;
}