ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【ABC253Ex】We Love Forest 题解

2022-05-30 17:35:52  阅读:133  来源: 互联网

标签:le Love int 题解 times ABC253Ex 集合 const mod


图上计数

Statement

给定一张有 \(n\) 个点,没有边的图

给定 \(m\) 条可能存在的边,有 \(k\) 次机会,每次可以等概率地抽取一条边并加入,同一条边可以被加入多次,\(m\) 条边中可能存在重边

对于每一个 \(k=1,2,\dots,n-1\) ,求出得到的图为森林的概率

\(n\le 14,n-1\le m\le 500\)

Solution

思路来自 https://atcoder.jp/users/GidroOttenok3797

概率直接转方案数

看到 \(n\le 14\), 想到这应该是一个带 \(2^n\) 复杂度的解法

考虑设 \(g[i][S]\) 表示 \(i\) 步过后,\(s\) 集合成为森林的方案数,

考虑转移,按照围绕一个基准点构造一个整体的思想,我们固定集合之中最小的点,dia 出一棵包含 \(lowbit(S)\) 的树来

\[g[i][S]=\sum_{lowbit(S)\in T\subseteq S} g[i-|T|+1][S/T]\times f[T] \]

其中 \(f[T]\) 表示 \(T\) 集合成为一棵树的方案数(花费 \(|T|-1\) 次机会),那么

\[f[S]=\begin{cases} 1,& |S|=1\\ \sum f[T]\times f[S/T]\times h(S,T),&otherwise \end{cases} \]

其中 \(h(S,T)\) 表示集合 \(S\) 和集合 \(T\) 的连边数量,容斥一下

\[h(S,T)=e(S|T)-e(S)-e(T) \]

其中 \(e(S)\) 表示 \(S\) 中的边的数量

这样的话,我们只需要 \(O(n2^n)\) 计算 \(e\) , \(O(3^n)\) 计算 \(f\) , \(O(n3^n)\) 计算 \(g\) 即可

答案为 \(\dfrac {g[i][2^n-1]\times i!}{m^i}\)

Code

#include<bits/stdc++.h>
#define ppc(x) __builtin_popcount(x)
#define lowbit(x) (-x&x)
using namespace std;
const int mod = 998244353;
const int N = 15;
const int M = 505;

char buf[1<<23],*p1=buf,*p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
int read(){
    int s=0,w=1; char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
    while(isdigit(ch))s=s*10+(ch^48),ch=getchar();
    return s*w;    
}
int ksm(int a,int b){
    int res=1;
    while(b){
        if(b&1)res=1ll*res*a%mod;
        a=1ll*a*a%mod,b>>=1;
    }
    return res;
}
void inc(int &a,int b){a=a>=mod-b?a-mod+b:a+b;}
void dec(int &a,int b){a=a>=b?a-b:a+mod-b;}
int add(int a,int b){return a>=mod-b?a-mod+b:a+b;}
int del(int a,int b){return a>=b?a-b:a+mod-b;}
 
int f[1<<N|5],e[1<<N|5],mp[N][N],g[N][1<<N|5],fac[N];
int n,m;

signed main(){
    n=read(),m=read();
    for(int i=fac[0]=1;i<=n;++i)
        fac[i]=1ll*fac[i-1]*i%mod;
    for(int i=1,u,v;i<=m;++i)
        u=read(),v=read(),
        mp[u][v]++,mp[v][u]++;
    
    for(int i=1;i<1<<n;++i){
        int j=log2(lowbit(i))+1,dlt=0;
        for(int k=1;k<=n;++k)
            if(i&(1<<k-1))inc(dlt,mp[j][k]);
        e[i]=add(e[i-lowbit(i)],dlt);
    }
    // for(int i=1;i<1<<n;++i)cout<<e[i]<<" ";puts("");

    f[0]=1;
    for(int i=1;i<1<<n;++i)
        if(ppc(i)==1)f[i]=1;
        else{
            for(int j=(i-1)&i;j;j=(j-1)&i)
                inc(f[i],1ll*f[j]*f[i^j]%mod*(e[i]-e[j]-e[i^j])%mod);
            f[i]=1ll*f[i]*ksm(2ll*(ppc(i)-1),mod-2)%mod;
        }
    // for(int i=1;i<1<<n;++i)cout<<f[i]<<" ";puts("");

    for(int i=0;i<n;++i)
        for(int j=0;j<1<<n;++j){
            if(i+1==ppc(j))g[i][j]=f[j];
            int must=lowbit(j);
            for(int k=j;k;k=(k-1)&j)
                if(k&must&&i>=ppc(k)-1)
                    inc(g[i][j],1ll*g[i-ppc(k)+1][j^k]*f[k]%mod);
        }
    
    for(int i=1;i<n;++i)
        printf("%d\n",1ll*g[i][(1<<n)-1]*fac[i]%mod*ksm(ksm(m,i),mod-2)%mod);
    return 0;
}

/*
3 2
1 2
2 3
*/

标签:le,Love,int,题解,times,ABC253Ex,集合,const,mod
来源: https://www.cnblogs.com/wyb-sen/p/16327493.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有