• JZOJ5957.【NOIP2018模拟11.7A组】scarborough fair


    PROBLEM

    求无向图期望联通快的个数。

    SOLUTION

    考虑将每一个联通块的贡献独立,我们需要得知一个联通块内部联通的概率,与其不与外面任何一个点联通的概率。

    考虑一种经典的做法。我们要求联通的概率,用1减去不连通的概率。我们设F[S]表示S这个联通块联通的概率。转移我们枚举编号最小的点所在的子集,设为T,那么F[S]+=F[T]*e[T][S xor T],e表示T这个子集不向另外节点连边的概率,也就是T与S^T这两个集合的边断开的期望。

    这个东西我们可以求出S每条边都不连的期望,除以T与S^T每条边都不连的期望,就可以得到这两个集合中间的那些边不相连的期望。

    最后枚举集合,再枚举集合的子集,总复杂度O(3^n)

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define ll long long 
    #define mo 998244353
    #define maxn 21
    using namespace std;
    
    int n,m,Mx,S,S0,T,i,j,k,x,y,cnt;
    ll ans,bet[1<<maxn],inv[1<<maxn],num[1<<maxn],f[1<<maxn],z,a[maxn][maxn];
    
    int low(int x){return x&-x;}
    
    ll ksm(ll x,ll y){
    	ll s=1;
    	for(;y;y>>=1,x=x*x%mo) if (y&1)
    		(s*=x)%=mo;
    	return s;
    }
    
    int main(){
    	freopen("fair.in","r",stdin);
    	freopen("fair.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for(i=0;i<n;i++) num[1<<i]=i;
    	for(i=1;i<=n;i++) for(j=1;j<=n;j++) a[i][j]=-1;
    	for(i=1;i<=m;i++){
    		scanf("%d%d%lld",&x,&y,&z);
    		a[x][y]=a[y][x]=z; 
    	}
    	bet[0]=1,inv[0]=1;
    	for(S=1;S<1<<n;S++){
    		i=num[low(S)];
    		bet[S]=bet[S^(1<<i)];
    		for(j=0;j<n;j++) if (j!=i&&a[i+1][j+1]!=-1&&((S>>j)&1)) 
    			(bet[S]*=a[i+1][j+1])%=mo;
    		inv[S]=ksm(bet[S],mo-2);
    	}
    	Mx=(1<<n)-1;
    	for(S=1;S<1<<n;S++) {
    		if (low(S)==S) f[S]=1; else{
    			S0=S-low(S);
    			for(j=S0;;j=((j-1)&S0)){
    				T=low(S)+j;
    				(f[S]+=f[T]*bet[S]%mo*inv[S^T]%mo*inv[T]%mo)%=mo;
    				if (j==0) break;
    			}
    			f[S]=(1+mo-f[S])%mo;
    		}
    		(ans+=f[S]*bet[Mx]%mo*inv[Mx^S]%mo*inv[S]%mo)%=mo;
    	}
    	printf("%lld",ans);
    }
    
  • 相关阅读:
    js代码细嚼慢咽
    HTML知识点记录

    css知识点
    算法第五章作业
    算法第五章上机实践报告
    算法第四章上机实践报告
    算法第四章作业
    算法第三章上机实践报告
    算法第三章作业
  • 原文地址:https://www.cnblogs.com/DeepThinking/p/11700968.html
Copyright © 2020-2023  润新知