[2020多校联考]环

Solution

每两个点都有一条有向边,所以是一个完全有向图。每次走最短的路径,所以是三元环(手玩样例亦可得)。
所以问题就转换为了统计有向图三元环期望个数。考虑转换补集的思想,一共可能有 \(\binom{n}{3}\) 个环,再减去不是环的。发现如果三个点构不成环,那么一定有其中一个点有两条出边。

对于已知的点和边,统计每个点的出度 \(d_i\),那么一定有 \(\binom{d_i}{2}\) 个三元组构不成环,需减去。(已经可以得 \(20\) 分了)
现在加入随机边的贡献。每条边的方向是等概率的,对于一个点 \(i\),它会向其它 \(n-1\) 个点连边,统计已经确定的且和 \(i\) 相连的边条数 \(s_i\),那么剩下的 \(n-s_i-1\) 条边就有 \(2^{n-s_i-1}\) 种情况,枚举有其中 \(j\) 条是 \(i\) 的出边的情况。这 \(j\) 条边会和现有的 \(d_i\) 条出边产生贡献,会造成 \(d_i\times j\) 个三元组构不成环,概率是 \(\frac{\binom{n-s_i-1}{j}}{2^{n-s_i-1}}\)。所以要减去

\[\sum_{j=0}^{n-s_i-1} \frac{\binom{n-s_i-1}{j}}{2^{n-s_i-1}}\times d_i\times j \]

化简

\[\frac{d_i}{2^{n-s_i-1}}\sum_{j=0}^{n-s_i-1} \binom{n-s_i-1}{j}\times j=\frac{d_i}{2^{n-s_i-1}}\sum_{j=0}^{n-s_i-1} \binom{n-s_i-2}{j-1}\times (n-s_i-1) \]

中间再用二项式定理搞掉

\[=\frac{d_i}{2^{n-s_i-1}}\times 2^{n-s_i-2}\times(n-s_i-1)=\frac{d_i(n-s_i-1)}{2} \]

再考虑两条随机边相互之间的贡献。同样枚举个数,有 \(j\) 条随机边是出边,那么就少 \(\binom{j}{2}\) 个环,加上概率,为

\[\sum_{j=0}^{n-s_i-1}\frac{\binom{n-s_i-1}{j}}{2^{n-s_i-1}}\times \binom{j}{2} \]

\(\binom{j}{2}\) 拆了,用上面相同的方式化简

\[\frac{n-s_i-1}{2^{n-s_i}}\sum_{j=0}^{n-s_i-1} \binom{n-s_i-2}{j-1}\times (j-1)=\frac{(n-s_i-1)(n-s_i-2)}{2^{n-s_i}}\sum_{j=0}^{n-s_i-1} \binom{n-s_i-3}{j-2} \]

\[=\frac{(n-s_i-1)(n-s_i-2)}{2^{n-s_i}}\times 2^{n-s_i-3}=\frac{(n-s_i-1)(n-s_i-2)}{8} \]

所以最后要求的值就是

\[\binom{n}{3}-\sum_{i=1}^{n} [\binom{d_i}{2}+\frac{d_i(n-s_i-1)}{2}+\frac{(n-s_i-1)(n-s_i-2)}{8}] \]

#include<stdio.h>
#define Mod 1000000007
#define N 100007
#define ll long long

inline int read(){
    int x=0,flag=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')flag=0;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
    return flag? x:-x;
}

ll qpow(ll x,ll y){
    ll ret=1,cnt=0;
    while(y>=(1LL<<cnt)){
        if(y&(1LL<<cnt)) ret=(ret*x)%Mod;
        x=(x*x)%Mod,cnt++;
    }
    return ret;
}

ll n,e;
ll d[N],s[N];
int main(){
    freopen("circle.in","r",stdin);
    freopen("circle.out","w",stdout);
    n=read(),e=read();
    for(int i=1;i<=e;i++){
        int u=read(),v=read();
        d[u]++,s[u]++,s[v]++;
    }
    ll ans=n*(n-1)%Mod*(n-2)%Mod*qpow(6LL,Mod-2)%Mod;
    ll n2=qpow(2LL,Mod-2),n8=qpow(8LL,Mod-2);
    for(int i=1;i<=n;i++){
        ll ret=d[i]*(d[i]-1)%Mod*n2%Mod;
        ret=(ret+d[i]*(n-s[i]-1)%Mod*n2%Mod)%Mod;
        ret=(ret+(n-s[i]-1)*(n-s[i]-2+Mod)%Mod*n8%Mod)%Mod;
        ans=((ans-ret)%Mod+Mod)%Mod;
    }
    printf("%lld",ans);
}
posted @ 2020-12-01 20:43  Kreap  阅读(88)  评论(0编辑  收藏  举报