zoukankan      html  css  js  c++  java
  • Evensgn 捡树枝

    问题 A: Evensgn 剪树枝

    时间限制: 1 Sec  内存限制: 128 MB

    题目描述

    繁华中学有一棵苹果树。苹果树有 n 个节点(也就是苹果),n − 1 条边(也就

    是树枝)。调皮的 Evensgn 爬到苹果树上。他发现这棵苹果树上的苹果有两种:一

    种是黑苹果,一种是红苹果。Evensgn 想要剪掉 k 条树枝,将整棵树分成 k + 1 个

    部分。他想要保证每个部分里面有且仅有一个黑苹果。请问他一共有多少种剪树枝

    的方案?

    输入

    第一行一个数字 n,表示苹果树的节点(苹果)个数。

    第二行一共 n − 1 个数字 p0, p1, p2, p3, ..., pn−2,pi 表示第 i + 1 个节点和 pi 节

    点之间有一条边。注意,点的编号是 0 到 n − 1。

    第三行一共 n 个数字 x0, x1, x2, x3, ..., xn−1。如果 xi 是 1,表示 i 号节点是黑

    苹果;如果 xi 是 0,表示 i 号节点是红苹果。

    输出

    输出一个数字,表示总方案数。答案对 109 + 7 取模。

    样例输入

    样例输入 2
    6
    0 1 1 0 4
    1 1 0 0 1 0
    样例输入 3
    10
    0 1 2 1 4 4 4 0 8
    0 0 0 1 0 1 1 0 0 1

    样例输出

    样例输出 1
    2
    样例输出 2
    1
    样例输出 3
    27

    提示


    数据范围



    对于 30% 的数据,1 ≤ n ≤ 10。



    对于 60% 的数据,1 ≤ n ≤ 100。



    对于 80% 的数据,1 ≤ n ≤ 1000。



    对于 100% 的数据,1 ≤ n ≤ 105。



    对于所有数据点,都有 0 ≤ pi ≤ n − 1,xi = 0 或 xi = 1。

    特别地,60% 中、80% 中、100% 中各有一个点,树的形态是一条链。

       之前这个人刚因为欠债把我坑了一回。。现在又来捡树枝了呜呜呜~~~~(>_<)~~~~

      一眼望去,树归无际。。没错!这道题就是一个很狠狠狠的树归!!

      ::

        我们设f[i][0]为以i为根节点是如果有k个黑苹果,那就正好对其子树剪了k刀,f[i][1]为对其子树剪了k-1刀

    因为我们发现如果总共有p个黑苹果,对于整颗树来说一定是剪了p-1根树枝的,那么状态转移一定是有上面俩个状态转移过来的。

    所以我们对这个树先进行一遍dfs,预处理出其fa和size数组,size数组的含义是其子树中(包括他自己)含有多少个黑苹果。

    那么对于节点i来说,我们要分两种情况进行考虑::

        ①:这个苹果是个黑的,那么所有他的子节点如果为son,f[i][1]一定是有f[son][0]转移过来的,因为包含他自己就代表着他自己没有办法被砍,那这个状态只能是1

        ②:如果这个苹果是红色的,那就要比较麻烦一点了。。首先对于f[i][0]是其所有子节点f[son][0]+f[son][1],带便这这条枝被砍掉,那么f[son][1]就会变为f[son][0],所以要求和。然后对所有的f[son][0]进行相乘(一个简单的分步乘法原理(⊙﹏⊙)b),这就是f[i][0],sum==f[i][0];

        而f[i][1]就为(sum/f[son][0]*f[son][1])的和;因为只有一个是少砍一个的,其他的都是砍满的,方案数相乘。

    所以最终的结果就是f[0][1](我是从0开始定义的,而p个苹果必须留一个,所以是1);

    除法的时候因为有取模,所以要用逆元处理一下即可。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<vector>
     6 using namespace std;
     7 #define mod 1000000007
     8 int n,m,num,x,y;
     9 int adj[1000001],w[1000001];
    10 struct edge{
    11     int s,t,next;
    12 }k[2000002];
    13 int read(){
    14     int sum=0;char ch=getchar();
    15     while(ch<'0'||ch>'9') ch=getchar();
    16     while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
    17     return sum;
    18 }
    19 void init(int s,int t){
    20     k[num].s=s;k[num].t=t;
    21     k[num].next=adj[s];adj[s]=num++;
    22     k[num].s=t;k[num].t=s;
    23     k[num].next=adj[t];adj[t]=num++;
    24 }
    25 int f[200002][20];
    26 int fa[200002],size[200002];
    27 long long ks(long long p,int n){
    28     long long sq=1;
    29     while(n){
    30         if(n&1) sq=sq*p%mod;
    31         p=p*p%mod;
    32         n>>=1;
    33     }
    34     return sq;
    35 }
    36 void dfs(int x){
    37     if(w[x]) size[x]=1;
    38     for(int i=adj[x];i!=-1;i=k[i].next){
    39         int o=k[i].t;
    40         if(o!=fa[x]){
    41             fa[o]=x;
    42             dfs(o);
    43             size[x]+=size[o];
    44         }
    45     }
    46 }
    47 void Dp(int x){
    48     long long sum=1;
    49     if(!w[x]){
    50         for(int i=adj[x];i!=-1;i=k[i].next){
    51             int o=k[i].t;
    52             if(o==fa[x]||!size[o]) continue;
    53             Dp(o);
    54             f[o][0]+=f[o][1];f[o][0]%=mod;
    55             sum*=f[o][0];sum%=mod;
    56         }
    57         f[x][0]=sum;
    58         for(int i=adj[x];i!=-1;i=k[i].next){
    59             int o=k[i].t;
    60             if(o==fa[x]||!size[o]) continue;
    61             int pl=sum*ks(f[o][0],mod-2)%mod*f[o][1]%mod;
    62             f[x][1]+=pl;f[x][1]%=mod;
    63         }
    64     }
    65     else{
    66         for(int i=adj[x];i!=-1;i=k[i].next){
    67             int o=k[i].t;
    68             if(o==fa[x]||!size[o]) continue;
    69             Dp(o);  f[o][0]+=f[o][1];f[o][0]%=mod;
    70             sum*=f[o][0];sum%=mod;
    71         }
    72         f[x][1]=sum;
    73     }
    74 }
    75 int main(){
    76     //freopen("tree.in","r",stdin);
    77     //freopen("tree.out","w",stdout);
    78     memset(fa,-1,sizeof(fa));
    79     memset(adj,-1,sizeof(adj));
    80     n=read();
    81     for(int i=1;i<n;++i){
    82         x=read();
    83         init(x,i);
    84     }
    85     for(int i=0;i<n;++i)
    86         w[i]=read();
    87     dfs(0);Dp(0);
    88     printf("%d
    ",f[0][1]);
    89     return 0;
    90 }
  • 相关阅读:
    centos7 安装配置手册
    常用mysql统计信息(mysql5.6)
    yum将需要安装的软件依赖下载到本地
    impala使用指南
    redis集群配置
    VIM
    Vim自动补全插件----YouCompleteMe安装与配置
    vim中自动格式化代码
    vscode_插件_shell格式化工具安装
    Anaconda+vscode 搭建开发环境
  • 原文地址:https://www.cnblogs.com/Maplers/p/7341524.html
Copyright © 2011-2022 走看看