zoukankan      html  css  js  c++  java
  • [cf1236F]Alice and the Cactus

    首先,我们要用到期望的一个性质:

    对于两个随机变量$X$和$Y$(不需要相互独立),有$E(X+Y)=E(X)+E(Y)$

    另外,对于一个仙人掌,令$n$为点数,$m$为边数,$c$为简单环个数,$X$为连通块数,则$X=n-(m-c)$(环可以看作有一条无意义的边,对于森林点-边即为连通块数)

    我们所求的即$E((X-E(X))^{2})$,将其展开即$E(X^{2})-E(X)^{2}$,后者$E(X)=E(n)-E(m)+E(c)$,以下以$E(m)$为例来考虑:

    令$x_{1},x_{2},...,x_{m}$表示每一条边是否被存在,即若其存在则$x_{i}=1$,否则$x_{i}=0$

    显然$m=sum_{i=1}^{m}x_{i}$,根据性质1,即$E(m)=sum_{i=1}^{m}E(x_{i})=frac{m}{4}$

    类似地,有$E(n)=frac{n}{2}$以及$E(c)=sum_{环}frac{1}{2^{环上点数}}$

    对于$E(X^{2})$,将其展开即$E(X^{2})=E(n^{2})+E(m^{2})+E(c^{2})-2E(nm)+2E(nc)-2E(mc)$,以下同样以$2E(mc)$为例来考虑:

    令$x_{1},x_{2},...,x_{m}$与之前相同,再定义$y_{1},y_{2},...,y_{c}$(其中$c$为环数)来表示每一个环是否存在(存在为1,不存在为0),则$E(mc)=E(sum_{i=1}^{m}x_{i}sum_{j=1}^{c}y_{j})$

    同样利用性质1展开,也就是$sum_{i=1}^{m}sum_{j=1}^{c}E(x_{i}y_{j})$,不难发现$E(x_{i}y_{j})=P(第i条边和第j个环同时存在)$,后者也就是第$i$条边和第$j$个环同时覆盖了多少个点的2的幂次

    简单对交点数分类讨论即可,时间复杂度可以通过预处理2幂次的逆元来做到严格线性,另外由于每一条边至多被覆盖一次,可以暴力枚举所有环上所有点

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 500005
     4 #define mod 1000000007
     5 struct Edge{
     6     int nex,to;
     7 }edge[N<<1];
     8 vector<pair<int,int> >v;
     9 int E,n,m,x,y,inv[N],head[N],r[N],dfn[N],f[N],dep[N],sum[N];
    10 int En,Em,Ec,En2,Em2,Ec2,Enm,Enc,Emc,EX,EX2,ans;
    11 void add(int x,int y){
    12     edge[E].nex=head[x];
    13     edge[E].to=y;
    14     head[x]=E++;
    15 }
    16 void dfs(int k,int fa,int s){
    17     dfn[k]=++dfn[0];
    18     f[k]=fa;
    19     dep[k]=s;
    20     for(int i=head[k];i!=-1;i=edge[i].nex)
    21         if (edge[i].to!=fa){
    22             if (!dfn[edge[i].to])dfs(edge[i].to,k,s+1);
    23             else{
    24                 if (dep[edge[i].to]>=s)continue;
    25                 int l=s-dep[edge[i].to]+1;
    26                 Ec=(Ec+inv[l])%mod;
    27                 Enc=(Enc+1LL*(n-l)*inv[l+1]+1LL*l*inv[l])%mod;
    28                 int s_same=l;
    29                 for(int j=k;;j=f[j]){
    30                     s_same=s_same+r[j]-2;
    31                     sum[j]=(sum[j]+inv[l])%mod;
    32                     if (j==edge[i].to)break;
    33                 }
    34                 Emc=(Emc+1LL*(m-s_same)*inv[l+2]+1LL*(s_same-l)*inv[l+1]+1LL*l*inv[l])%mod;
    35                 sum[0]=(sum[0]+inv[l])%mod;
    36                 v.push_back(make_pair(k,edge[i].to));
    37             }
    38         }
    39 }
    40 int main(){
    41     inv[0]=1;
    42     for(int i=1;i<N;i++)inv[i]=1LL*(mod+1)/2*inv[i-1]%mod;
    43     scanf("%d%d",&n,&m);
    44     memset(head,-1,sizeof(head));
    45     for(int i=1;i<=m;i++){
    46         scanf("%d%d",&x,&y);
    47         add(x,y);
    48         add(y,x);
    49         r[x]++,r[y]++;
    50     }
    51     En=1LL*n*inv[1]%mod;
    52     Em=1LL*m*inv[2]%mod;
    53     En2=(1LL*n*(n-1)%mod*inv[2]+1LL*n*inv[1])%mod;
    54     Enm=(1LL*m*(n-2)%mod*inv[3]+2LL*m*inv[2])%mod;
    55     for(int i=1;i<=n;i++)
    56         for(int j=head[i];j!=-1;j=edge[j].nex){
    57             x=i,y=edge[j].to;
    58             if (x<y)Em2=(Em2+1LL*(m-r[x]-r[y]+1)*inv[4]+1LL*(r[x]+r[y]-2)*inv[3]%mod+inv[2])%mod;
    59         }
    60     dfs(1,0,0);
    61     for(int i=0;i<v.size();i++){
    62         x=v[i].first,y=v[i].second;
    63         int l=dep[x]-dep[y]+1,s_same=inv[l];
    64         for(int j=x;;j=f[j]){
    65             s_same=((s_same+sum[j]-inv[l])%mod+mod)%mod;
    66             if (j==y)break;
    67         }
    68         Ec2=(Ec2+1LL*(sum[0]+mod-s_same)*inv[l]+1LL*(s_same+mod-inv[l])*inv[l-1]+inv[l])%mod;
    69     }
    70     EX=((0LL+En-Em+Ec)%mod+mod)%mod;
    71     EX2=((0LL+En2+Em2+Ec2-2*Enm+2*Enc-2*Emc)%mod+mod)%mod;
    72     ans=(EX2-1LL*EX*EX%mod+mod)%mod;
    73     printf("%d",ans);
    74 }
    View Code
  • 相关阅读:
    jsp第三次作业
    软件测试第一次
    jsp第二次作业
    JSP第七次作业
    JSP第六次作业
    JSP第五次作业
    软件测试第二次作业
    JSP第四次作业(二)
    JSP第四次作业(一)
    JSP第三次作业
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14516344.html
Copyright © 2011-2022 走看看