• AtCoder Regular Contest 086 E


      好强的题。

      方案不好算,改成算概率,注意因为是模意义下的概率所以直接乘法逆元就好不要傻傻地开double。

      设$f[i][d][0]$为第i个节点离d层的球球走到第i个点时第i个点没有球的概率, $f[i][d][1]$为有1个球的概率, $f[i][d][2]$为有2个球及以上的概率。

      我们可以把$f[i]$看成一个队列, 然后从儿子转移的时候, 就是把儿子的队列一个一个合并起来,最后在队列头加上一个$f[i][0]$, 并且把队列里的所有$f[i][0$~$d][2]$加上$f[i][0$~$d][0]$,并且$f[i][0$~$d][2]$变成0就好了。

      合并的时候转移为:

      $f[i][d][0]=f[i][d][0]*f[j][d][0]$

      $f[i][d][1]=f[i][d][1]*f[j][d][0]+f[i][d][0]*f[j][d][1]$

      $f[i][d][2]=f[i][d][0]*f[j][d][2]+f[i][d][1]*f[j][d][2]+f[i][d][1]*f[j][d][1]+f[i][d][2]*f[j][d][2]+f[i][d][2]*f[j][d][1]+f[i][d][2]*f[j][d][0]$

      复杂度为O(N),因为每层元素只加1,交集最多为N。

    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #define ll long long
    #define MOD(x) ((x)>=mod?(x)-mod:(x))
    using namespace std;
    const int maxn=500010, mod=1e9+7;
    struct tjm{int too, pre;}e[maxn<<1];
    struct poi{int f[3];};
    int n, x, ans, tot, tott;
    int last[maxn], root[maxn];
    vector<poi>q[maxn];
    inline void read(int &k)
    {
        int f=1; k=0; char c=getchar();
        while(c<'0' || c>'9') c=='-' && (f=-1), c=getchar();
        while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();
        k*=f;
    }
    inline void add(int x, int y){e[++tot]=(tjm){y, last[x]}; last[x]=tot;}
    inline int merge(int x, int y)
    {
        if(q[x].size()<q[y].size()) swap(x, y);
        int nx=q[x].size()-1, ny=q[y].size()-1;
        for(int i=0;i<=ny;i++) 
        {
            int sum0=0, sum1=0, sum2=0;
            sum0=1ll*q[x][nx-i].f[0]*q[y][ny-i].f[0]%mod;
            sum1=(1ll*q[x][nx-i].f[1]*q[y][ny-i].f[0]+1ll*q[x][nx-i].f[0]*q[y][ny-i].f[1])%mod;
            for(int j=0;j<3;j++)
                for(int k=2;j+k>=2;k--)
                    sum2=(1ll*sum2+1ll*q[x][nx-i].f[j]*q[y][ny-i].f[k])%mod;
            q[x][nx-i].f[0]=sum0; q[x][nx-i].f[1]=sum1; q[x][nx-i].f[2]=sum2;
        }
        q[y].clear(); return x;
    }
    void dfs(int x, int fa)
    {
        if(!last[x]) root[x]=++tott; int dep=0;
        for(int i=last[x], too;i;i=e[i].pre)
        if((too=e[i].too)!=fa)
        {
            dfs(too, x);
            if(!root[x]) root[x]=root[too];
            else dep=max(dep, (int)min(q[root[x]].size(), q[root[too]].size())), root[x]=merge(root[x], root[too]);
        }
        int nx=q[root[x]].size()-1; 
        for(int i=0;i<dep;i++) 
            q[root[x]][nx-i].f[0]=MOD(q[root[x]][nx-i].f[0]+q[root[x]][nx-i].f[2]), q[root[x]][nx-i].f[2]=0;
        poi tmp; tmp.f[1]=tmp.f[0]=(mod+1)>>1; tmp.f[2]=0; q[root[x]].push_back(tmp);
    }
    inline int power(int a, int b)
    {
        int ans=1;
        for(;b;b>>=1, a=1ll*a*a%mod)
        if(b&1) ans=1ll*ans*a%mod;
        return ans;
    }
    int main()
    {
        read(n);
        for(int i=1;i<=n;i++) read(x), add(x, i);
        dfs(0, -1); 
        for(int i=0;i<q[root[0]].size();i++) ans=MOD(ans+q[root[0]][i].f[1]);
        printf("%lld
    ", 1ll*ans*power(2, n+1)%mod);
    }
    View Code
  • 相关阅读:
    adb shell top
    数据清洗的方法
    Devices Tree加载流程
    Android驱动之设备树简介
    序列模式挖掘综述
    python 实现kmeans聚类
    numpy中sum(axis=0)和axis=1的计算原理
    win7 VMware下安装centos和Ubuntu共存
    python数据标准化
    python 用PIL Matplotlib处理图像的基本操作
  • 原文地址:https://www.cnblogs.com/Sakits/p/8027335.html
Copyright © 2020-2023  润新知