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

9 篇文章 0 订阅
6 篇文章 0 订阅

这道题运用了很多数学知识(唉,真羡慕你们高数好的…….)
首先我们扔掉提示。。。。。
尝试枚举最小生成树的最大边x,令 g(x) 表示答案<=x的概率
发现答案可以表示成

10xg(x)dx

根据分部积分法,原式=
110g(x)dx=10(1g(x))dx

即答案=答案>=x的概率的积分
(离散上也有类似公式,可用有限微积分导出,图形也很好想)

f(x)=1g(x) 则对于f(x)问题转变成一张图,边有x的概率出现,图不联通的概率;
然后可以状压dp求解(注意到dp数组是关于x的多项式)

#include<bits/stdc++.h>
#define rep(i,k,n) for(int i=k;i<=n;i++)
#define PB push_back
using namespace std;
const int N=13;
typedef long long ll;
typedef __float128 ld;
typedef vector<ll> ploy;
ploy operator + (const ploy& a,const ploy& b){
    ploy c(max(a.size(),b.size()),0);
    int sz_a=a.size()-1,sz_b=b.size()-1;
    rep(i,0,sz_a)c[i]+=a[i];
    rep(i,0,sz_b)c[i]+=b[i];
    return c;
}
ploy operator - (const ploy& a,const ploy& b){
    ploy c(max(a.size(),b.size()),0);
    int sz_a=a.size()-1,sz_b=b.size()-1;
    rep(i,0,sz_a)c[i]+=a[i];
    rep(i,0,sz_b)c[i]-=b[i];
    return c;
}
ploy operator * (const ploy& a,const ploy& b){
    ploy c(a.size()+b.size(),0);
    int sz_a=a.size()-1,sz_b=b.size()-1;
    rep(i,0,sz_a)rep(j,0,sz_b)c[i+j]+=a[i]*b[j]; 
    return c;
}
ld jifen_1(const ploy& a){
    ld res=0.0;
    int sz_a=a.size()-1;
    rep(i,0,sz_a)res+=(ld)a[i]/(i+1);
    return res; 
}
ploy f[1<<N],pow_1_x[N*N],g(1,1);
int a[N],n,m,cnt[1<<N],S;
void init(){
    rep(i,1,S)cnt[i]=cnt[i-(i&-i)]+1;
    pow_1_x[0].PB(1);
    pow_1_x[1].PB(1);pow_1_x[1].PB(-1);
    rep(i,2,m)
        pow_1_x[i]=pow_1_x[i-1] * pow_1_x[1]; 
}
int main(){
    scanf("%d%d",&n,&m);S=(1<<n)-1;
    int x,y;
    rep(i,1,m){
        scanf("%d%d",&x,&y);
        a[x]|=(1<<(y-1));
        a[y]|=(1<<(x-1));
    }init();
    rep(s,1,S){
        new (&f[s])ploy(1,1);
        int who=s&-s;
        for(int j=s^who;j;j=(j-1)&(s^who)){
            int i=s^j,edge=0;
            rep(k,1,n)if((i>>(k-1))&1)edge+=cnt[a[k]&j];
            f[s]=f[s] - f[i]*pow_1_x[edge];
        }
    }g=g - f[S];
    double ans=jifen_1(g);
    printf("%.6lf",ans);
}

如果不扔掉提示,有更方便做法;
传送门
其实提示用上述方法也易证

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值