• luogu5007 DDOSvoid 的疑惑 (树形dp)


    我们来算每个点出现在的集合的个数

    设f[i]为i出现的集合个数,g[i]是只选子树i 可以有多少种选法

    那就有$g[i]=1+prodlimits_{j是i的孩子}{g[j]} , f[i]=f[fa[i]]*prodlimits_{j是i的兄弟}{f[j]}$

    这个兄弟的积可以直接用一个逆元 或者是做前缀积和后缀积然后乘起来,但千万不要一边记着后缀积一边又进子树dfs 你孩子全都给你改没了(摔

    那我们肯定能不带log就不带嘛

     1 #include<bits/stdc++.h>
     2 #define CLR(a,x) memset(a,x,sizeof(a))
     3 using namespace std;
     4 typedef long long ll;
     5 typedef pair<int,int> pa;
     6 const int maxn=1e6+10,P=1e8+7;
     7 
     8 inline ll rd(){
     9     ll x=0;char c=getchar();int neg=1;
    10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    12     return x*neg;
    13 }
    14 
    15 int eg[maxn*2][2],egh[maxn],ect;
    16 int N,T,stk[maxn];
    17 ll choi[maxn],dp[maxn];
    18 ll pre[maxn],ans;
    19 
    20 inline void adeg(int a,int b){
    21     eg[++ect][0]=b,eg[ect][1]=egh[a],egh[a]=ect;
    22 }
    23 
    24 void dfs1(int x,int f){
    25     choi[x]=1;
    26     for(int i=egh[x];i;i=eg[i][1]){
    27         int b=eg[i][0];if(b==f) continue;
    28         dfs1(b,x);
    29         choi[x]=choi[x]*choi[b]%P;
    30     }
    31     choi[x]++;choi[x]%=P;
    32 }
    33 
    34 void dfs2(int x,int f){
    35     ans+=dp[x]*(T?x:1)%P,ans%=P;
    36     int n=0;
    37     for(int i=egh[x];i;i=eg[i][1]){
    38         int b=eg[i][0];if(b==f) continue;
    39         stk[++n]=b;
    40     }
    41     pre[n+1]=1;
    42     for(;n;n--) pre[n]=pre[n+1]*choi[stk[n]]%P;
    43     ll a=dp[x];
    44     for(int i=egh[x];i;i=eg[i][1]){
    45         int b=eg[i][0];if(b==f) continue;
    46         ++n;dp[b]=a*pre[n+1]%P;
    47         a*=choi[b],a%=P;
    48     }
    49     for(int i=egh[x];i;i=eg[i][1]){
    50         int b=eg[i][0];
    51         if(b==f) continue;
    52         dfs2(b,x);
    53     }
    54 }
    55 
    56 int main(){
    57     //freopen("","r",stdin);
    58     int i,j,k;
    59     N=rd(),T=rd();
    60     for(i=1;i<N;i++){
    61         int a=rd(),b=rd();
    62         adeg(a,b);adeg(b,a);
    63     } 
    64     dfs1(1,0);dp[1]=1;dfs2(1,0);
    65     printf("%lld
    ",(ans+P)%P);
    66     return 0;
    67 }
  • 相关阅读:
    转 linux shell自定义函数(定义、返回值、变量作用域)介绍
    转 Shell调试篇
    WIN2012的桌面和开始菜单跑到什么地方去了
    转 awr自动收集脚本
    Troubleshooting Guide for ORA-12541 TNS: No Listener
    test
    向Linus学习,让代码具有good taste
    php 页面展示
    c++ list sort
    c++ word类型
  • 原文地址:https://www.cnblogs.com/Ressed/p/9911877.html
Copyright © 2020-2023  润新知