zoukankan      html  css  js  c++  java
  • 51Nod1679 连通率

    题目看这里

    一个简单的计数问题

    我们先考虑O(n^2)的做法

    对每个点dfs一次,求出d[i]表示i的深度,那么对答案贡献就是Σ2^(n-d[i])

    那么我们考虑用数据结构动态维护这个d[i],显然可以用线段树来维护dfs序做到

    复杂度O(n lg n) 效率很高rank8


    看了下solution突然才发现别人都不是这么做的!


    不管了反正跑得过而且跑的快。。就是代码比较丑陋

    #pragma GCC opitmize("O3")
    #pragma G++ opitmize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define M 1000000007
    #define LL long long
    #define mid (l+r>>1)
    #define N 100010
    using namespace std;
    const int inv=500000004;
    struct edge{ int v,nt; } G[N<<1];
    int n,cnt=0,h[N],w[N],t,d[N],l[N],r[N]; LL s[N<<2],c[N<<2],ans=0;
    inline void ad(LL& x,LL y){ x=(x+y)%M; }
    inline void mul(LL& x,LL y){ x=x*y%M; }
    inline LL pow(LL x,LL k,LL s=1){
        for(;k;x=x*x%M,k>>=1) k&1?s=s*x%M:0;
        return s;
    }
    inline void build(int l,int r,int x){
        if(l==r){ s[x]=pow(2,n-d[w[l]]-1); c[x]=1; return; }
        build(l,mid,x<<1);
        build(mid+1,r,x<<1|1);
        s[x]=(s[x<<1]+s[x<<1|1])%M; c[x]=1;
    }
    inline void pd(int x){
        if(c[x]>1){
            mul(c[x<<1],c[x]);
            mul(c[x<<1|1],c[x]);
            mul(s[x<<1],c[x]);
            mul(s[x<<1|1],c[x]);
            c[x]=1;
        }
    }
    inline void update(int l,int r,int x,int L,int R,LL k){
        if(L<=l && r<=R){ mul(s[x],k); mul(c[x],k); return; }
        pd(x);
        if(L<=mid) update(l,mid,x<<1,L,R,k);
        if(mid<R) update(mid+1,r,x<<1|1,L,R,k);
        s[x]=(s[x<<1]+s[x<<1|1])%M;
    }
    inline LL query(int l,int r,int x,int L,int R){
        if(L<=l && r<=R) return s[x];
        pd(x); LL ans=0;
        if(L<=mid) ad(ans,query(l,mid,x<<1,L,R));
        if(mid<R) ad(ans,query(mid+1,r,x<<1|1,L,R));
        return ans;
    }
    inline void dfs(int x){
        w[++t]=x; l[x]=t;
        for(int v,i=h[x];i;i=G[i].nt)
            if(!l[v=G[i].v]){ d[v]=d[x]+1; dfs(v); }
        r[x]=t;
    }
    inline void cal(int x,int p){
        ad(ans,query(1,n,1,1,n));
        for(int v,i=h[x];i;i=G[i].nt)
            if((v=G[i].v)!=p){
                update(1,n,1,l[v],r[v],4);
                update(1,n,1,1,n,inv);
                cal(v,x); 
                update(1,n,1,l[v],r[v],(LL)inv*inv%M);
                update(1,n,1,1,n,2);
            }
    }
    int main(){
        scanf("%d",&n);
        for(int x,y,i=1;i<n;++i){
            scanf("%d%d",&x,&y);
            G[++cnt]=(edge){y,h[x]}; h[x]=cnt;
            G[++cnt]=(edge){x,h[y]}; h[y]=cnt;
        }
        dfs(1);
        build(1,n,1);
        cal(1,0);
        ad(ans,-n*pow(2,n-1)%M);
        printf("%lld
    ",(ans+M)%M*inv%M);
    }

  • 相关阅读:
    windbg常用命令
    Windbg双机调试环境配置(Windows7/Windows XP+VirtualBox/VMware+WDK7600)
    SVN使用说明文档
    JavaScript-浏览器兼容之客户端检测
    JavaScript-执行环境
    JavaScript-函数
    JavaScript-静态私有变量
    JavaScript-构造函数模式
    JavaScript 自执行函数剖析
    easyui如何在datagrid 每行增加超链接
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477124.html
Copyright © 2011-2022 走看看