2018.12.14-dtoj3192: Smuggling Marbles

题目描述:

Sunke有一棵N + 1个点的树,其中0为根,每个点上有0或1个石子,Sunke会不停的进行如下操作直至整棵树没有石子:

把0上面的石子从树上拿走放入口袋;

把每个点上的石子移到其父亲上;

对于每个点,若其石子数≥ 2,则移除该点所有石子(不 放入口袋)。

求对于所有2^{N+1}2N+1种放置石子的方案,最终Sunke口袋中石子数的和为多少,对1000000007取模。

1 ≤ N < 200000,有一部分数据满足1 ≤ N < 2000。

算法标签:启发式DP(首次听说dp可以启发式!nb)

网路上有很多详细清晰的题解(懒惰不想写题解

以下代码:

#include<bits/stdc++.h>
#define il inline
#define LL long long
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
const int N=2e5+5,p=1e9+7;
int n,head[N],ne[N],to[N],rt[N],inv2=p-p/2,cnt;
struct node{
    int f[3];
    node(int a,int b,int c){f[0]=a;f[1]=b;f[2]=c;}
};vector<node> q[N];
il int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return f*x;}
il void insert(int x,int y){ne[++cnt]=head[x];head[x]=cnt;to[cnt]=y;}
il int mu(int x,int y){if(x+y>=p)return x+y-p;return x+y;}
il LL ksm(LL a,int y){LL b=1;while(y){if(y&1)b=b*a%p;a=a*a%p;y>>=1;}return b;}
il int merge(int x,int y){
    if(q[x].size()<q[y].size())swap(x,y);
    int xsz=q[x].size(),ysz=q[y].size();
    for(int i=0;i<ysz;i++){
        int px=xsz-i-1,py=ysz-i-1;
        int t0,t1,t2;
        t0=1ll*q[x][px].f[0]*q[y][py].f[0]%p;
        t1=mu(1ll*q[x][px].f[0]*q[y][py].f[1]%p,1ll*q[x][px].f[1]*q[y][py].f[0]%p);
        t2=mu(1ll*q[x][px].f[2]*q[y][py].f[2]%p,mu(1ll*q[x][px].f[2]*q[y][py].f[1]%p,1ll*q[x][px].f[2]*q[y][py].f[0]%p));
        t2=mu(mu(t2,1ll*q[x][px].f[0]*q[y][py].f[2]%p),mu(1ll*q[x][px].f[1]*q[y][py].f[2]%p,1ll*q[x][px].f[1]*q[y][py].f[1]%p));
        q[x][px]=node(t0,t1,t2);
    }
    q[y].clear();return x;
}
il void dfs(int x){
    rt[x]=x;int dep=0;
    if(!head[x]){
        q[x].push_back(node(inv2,inv2,0));return;
    }
    for(int i=head[x];i;i=ne[i]){
        dfs(to[i]);
        dep=max(dep,(int)min(q[rt[x]].size(),q[rt[to[i]]].size()));
        rt[x]=merge(rt[x],rt[to[i]]);
    }
    int now=rt[x];int s=q[now].size()-1;
    for(int i=0;i<dep;i++){
        q[now][s-i].f[0]=mu(q[now][s-i].f[2],q[now][s-i].f[0]);q[now][s-i].f[2]=0;
    }
    q[now].push_back(node(inv2,inv2,0));
}
int main()
{
    n=read();for(int i=1;i<=n;i++){int x=read();insert(x,i);}
    dfs(0);LL ans=0;
    for(int i=0;i<q[rt[0]].size();i++)
        ans=mu(ans,q[rt[0]][i].f[1])%p;
    printf("%lld
",ans*ksm(2,n+1)%p);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Jessie-/p/10118386.html