繁华模拟赛 Evensgn剪树枝

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
const int maxn = 100005;
const ll mod = 1000000007;
struct edge{
    int to;
    int nxt;
};
int n,f[maxn][2],col[maxn];
int cnt,head[maxn];
edge e[maxn];
void add_edge(int u,int v){
    cnt++;
    e[cnt].to = v;
    e[cnt].nxt = head[u];
    head[u] = cnt;
}
ll q_mul(ll a,ll b){
    ll ans = 0;
    while(b){
        if(b&1){
            ans = (ans + a) % mod;
        }
        a = (a + a) % mod;
        b >>= 1;
    }
    return ans;
}
ll q_pow(ll a,ll b){
    ll ans = 1;
    while(b){
        if(b&1){
            ans = q_mul(ans,a);
        }
        a = q_mul(a,a);
        b >>= 1;
    }
    return ans;
}
void input(){
    cin>>n;
    int cmd;
    for(int i = 1;i < n;i++){
        cin>>cmd;
        add_edge(cmd,i);
    }
    for(int i = 0;i < n;i++){
        cin>>col[i];
    }
}
void dfs(int u){
    if(!head[u]){
        if(col[u]) f[u][1] = 1;
        else f[u][0] = 1;
        return;
    }
    ll sum = 1;
    int v;
    if(col[u]){
        for(int i = head[u];i;i = e[i].nxt){
            v = e[i].to;
            dfs(v);
            sum = q_mul(sum,f[v][0] + f[v][1]);
        }
        f[u][1] = sum;
        return;
    }else{
        for(int i = head[u];i;i = e[i].nxt){
            v = e[i].to;
            dfs(v);
            sum = q_mul(sum,f[v][0] + f[v][1]);
        }
        f[u][0] = sum;
        for(int i = head[u];i;i = e[i].nxt){
            v = e[i].to;
            f[u][1] += q_mul(f[v][1],q_mul(sum,q_pow(f[v][0] + f[v][1],mod-2)));
        }
        return;
    }
}
int main(){
    freopen("tree.in","r",stdin);
    freopen("tree.out","w",stdout);
    ios::sync_with_stdio(false);
    input();
    dfs(0);
    cout<<f[0][1];
    return 0;
}

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
using namespace std;

#define ll long long
const int MAXN = 1e5 + 10;
const int MOD  = 1e9 + 7;

ll f[MAXN][2];
int point[MAXN] = {0}, nxt[MAXN * 2] = {0}, v[MAXN * 2] = {0}, tot = 0;
bool color[MAXN] = {0};
int n;

inline void addedge(int x, int y)
{
    tot++;
    nxt[tot] = point[x]; point[x] = tot; v[tot] = y;
}

void dfs(int now, int father)
{
    f[now][0] = 1;
    f[now][1] = 0;
    for (int tmp = point[now]; tmp; tmp = nxt[tmp])
        if (v[tmp] != father)
        {
            dfs(v[tmp], now);
            f[now][1] = (f[now][1] * f[v[tmp]][0]) % MOD;
            f[now][1] = (f[now][1] + f[now][0] * f[v[tmp]][1]) % MOD;
            f[now][0] = (f[now][0] * f[v[tmp]][0]) % MOD;
        }
    if (color[now])
        f[now][1] = f[now][0];
    else
        f[now][0] = (f[now][0] + f[now][1]) % MOD;
}

int main()
{
    freopen("tree.in", "r", stdin);
    freopen("tree.out", "w", stdout);
    scanf("%d", &n);
    for (int i = 2; i <= n; i++)
    {
        int x;
        scanf("%d", &x);
        addedge(i, x + 1); addedge(x + 1, i);
    }
    for (int i = 1; i <= n; i++)
    {
        int x;
        scanf("%d", &x);
        if (x == 1) color[i] = true;
        else color[i] = false;
    }
    dfs(1, 0);
    cout << f[1][1] << endl;
}
时间: 2024-10-16 21:09:30

繁华模拟赛 Evensgn剪树枝的相关文章

[繁华模拟赛]Evensgn 剪树枝

Evensgn 剪树枝 题目 繁华中学有一棵苹果树.苹果树有 n 个节点(也就是苹果),n − 1 条边(也就 是树枝).调皮的 Evensgn 爬到苹果树上.他发现这棵苹果树上的苹果有两种:一 种是黑苹果,一种是红苹果.Evensgn 想要剪掉 k 条树枝,将整棵树分成 k + 1 个 部分.他想要保证每个部分里面有且仅有一个黑苹果.请问他一共有多少种剪树枝 的方案? INPUT 第一行一个数字 n,表示苹果树的节点(苹果)个数. 第二行一共 n − 1 个数字 p0, p1, p2, p3,

繁华模拟赛 Evensgn与字符矩阵

#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> using namespace std; const int maxn = 2050; int n,m,ans; char s[maxn][maxn]; bool ok; bool vis[maxn]; int main(){ freopen("evensg

繁华模拟赛 Evensgn的债务

#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #define ll int using namespace std; const int maxn = 1000005; ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(

繁华模拟赛 Evensgn玩序列

#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> using namespace std; const int maxn = 5000; int n,a[maxn],b[maxn],c[maxn],rka[maxn],rkb[maxn],rkc[maxn]; bool visa[maxn],visb[maxn],vi

Evensgn 剪树枝

问题 A: Evensgn 剪树枝 时间限制: 1 Sec  内存限制: 128 MB 题目描述 繁华中学有一棵苹果树.苹果树有 n 个节点(也就是苹果),n − 1 条边(也就 是树枝).调皮的 Evensgn 爬到苹果树上.他发现这棵苹果树上的苹果有两种:一 种是黑苹果,一种是红苹果.Evensgn 想要剪掉 k 条树枝,将整棵树分成 k + 1 个 部分.他想要保证每个部分里面有且仅有一个黑苹果.请问他一共有多少种剪树枝 的方案? 输入 第一行一个数字 n,表示苹果树的节点(苹果)个数.

繁华模拟赛 ljw分雕塑

/* 用f[i][k]表示考虑到第i个雕塑,分成k组,可不可行(这是一个bool类型的数组) 转移: f[i][k]=f[j][k-1],sum[i]-sum[j]合法 */ #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> using namespace std; typedef long long ll; const int max_n = 2010;

繁华模拟赛 找十字架

#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> using namespace std; int n; char s[205][205],cmd; int main(){ freopen("puzzle.in","r",stdin); freopen("puzzle

繁华模拟赛 Vincent的城堡

#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll mod = 1000000007; ll n,k,c[20][20]; ll ansa,ansb,ans; void get_c(){ for(int i = 1;i

繁华模拟赛 ljw搭积木

#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> using namespace std; const int maxn = 6005; int n,x[maxn]; int cmd,cnt,ans,max_x; int main(){ freopen("box.in","r"