bzoj 3925: [Zjoi2015]地震后的幻想乡

题目大意:给你n个点m条边,每条边的边权都是0~1的一个随机数,让你求一个最小瓶颈生成树的期望


虽然没有看懂,但还是先膜拜 http://wjmzbmr.com/archives/zjoi-2015-day-1%E9%A2%98%E8%A7%A3/

后来又膜拜了一下std,就幻想乡了。。。

就在这时,机房的zyf大神表示这题太水了,已经Ac了,于是速去膜拜

终于大概弄懂了

首先设f(x)为x==ans的概率密度函数,定义 F(x)=∫f(x)dx

我们惊讶的发现

ans=∫x*f(x)dx=∫xd(F(x))

再根据分部积分

ans=∫xd(F(x))=xF(x)-∫F(x)dx

然后我们发现F(x)代表答案<=ans的概率,即等价于每条边有x的概率出现,原图连通的概率,这个乱搞就可以了


#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cassert>
#include<iostream>
#include<algorithm>
#define PB push_back
#define in(x,y) (((y)>>((x)-1))&1)
using namespace std;
const int maxn=1<<10,maxm=49;
typedef long long int64;
typedef __float128 ld;
typedef vector<int64> poly;
poly operator -(const poly &a,const poly &b){
	poly res(max(a.size(),b.size()),0);
	for (int i=0;i<a.size();++i) res[i]+=a[i];
	for (int i=0;i<b.size();++i) res[i]-=b[i];
	return res;
}
poly operator *(const poly &a,const poly &b){
	poly res(a.size()+b.size()-1,0);
	for (int i=0;i<a.size();++i) for (int j=0;j<b.size();++j) res[i+j]+=a[i]*b[j];
	return res;
}
struct Te{int x,y;}e[maxm];
int n,m;
void init(){
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;++i) scanf("%d%d",&e[i].x,&e[i].y); 
}
ld integrate(poly x){
	ld ans=0;
	for (int i=0;i<x.size();++i) ans+=ld(1.0)*x[i]/(i+1);
	return ans;
}
poly f[maxn];
void work(){ // 状态为i的全部连通的概率(是一个关于每条边出现概率是x的多项式) 
	poly p,tmp; p.clear(); p.PB(1); p.PB(-1); int ss=1<<n;
	
	f[1].clear(); f[1].PB(1);
	for (int i=3;i<ss;i+=2){
		f[i].clear(); f[i].PB(1);
		for (int s=(i-1)&i;s;s=(s-1)&i) if (s&1){
			int k=0;
			for (int j=1;j<=m;++j) if (in(e[j].x,i) && in(e[j].y,i) && (in(e[j].x,s) ^ in(e[j].y,s))) ++k;
			tmp=f[s]; while (k--) tmp=tmp*p; f[i]=f[i]-tmp;
		}
	}
	
	poly ans; ans.clear(); ans.PB(1); ans=ans-f[ss-1];
	printf("%.6f\n",(double)integrate(ans));
}
int main(){
	init();
	work();
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值