BZOJ 3925: [Zjoi2015]地震后的幻想乡(概率)

CLJ就是喜欢出ctsc上讲的东西,看来还是得找时间把他的那几道题做下

首先记f(x)为答案>x的概率,那么把这个东西从0到1积分就是答案了

f(x)<=>边小于x不能使图联通的概率

这个有点难求,考虑求使图联通的概率

 记f(s)为集合s联通的概率,那么f(s)=1-sigma(f(s')*(1-x)^cnt) (s'属于s且s'一定包含某点k,cnt为链接s'与Cs s'的边数)

可以发现f(s)是个多项式,就可以积分了

由于还没用上64位评测系统,double还是不能过,只好用__float128,比较慢而已

CODE:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef vector<__float128> ploy;
ploy operator + (ploy x,ploy y){
    ploy ans(max(x.size(),y.size()),0);
    for (int i=0;i<ans.size();i++) {
        if (i<x.size()) ans[i]+=x[i];
        if (i<y.size()) ans[i]+=y[i];
    }
    return ans;
}
ploy operator - (ploy x,ploy y) {
    ploy ans(max(x.size(),y.size()),0);
    for (int i=0;i<ans.size();i++) {
        if (i<x.size()) ans[i]+=x[i];
        if (i<y.size()) ans[i]-=y[i];
    }
    return ans;
}
ploy operator * (ploy x,ploy y) {
    ploy ans(x.size()+y.size()-1,0);
    for (int i=0;i<x.size();i++) 
        for (int j=0;j<y.size();j++) 
            ans[i+j]+=x[i]*y[j];
    return ans;
}
bool b[1040];
ploy f[1040],quick[100];
int n,m;
struct edges{int x,y;}e[100];
ploy ONE(1,1);
inline void print(ploy x){
    printf("%d\n",x.size());
    for (int i=0;i<x.size();i++) printf("%lf ",double(x[i]));
    printf("\n");
}
void dp(int x){
    if (b[x]) return ;
    b[x]=1;
    ploy tmp(0,0);
    for (int i=1;i<(1<<n);i++) {
        if (!(i&1)) continue;
        if ((i&x)!=i) continue;
        if (i==x) continue;
        int j=x^i;
        int cnt=0;
        for (int k=1;k<=m*2;k++) 
            if (i&(1<<e[k].x)&&j&(1<<e[k].y)) cnt++;
        dp(i);
        tmp=tmp+f[i]*quick[cnt];
    }
    f[x]=ONE-tmp;
}
__float128 cal(ploy x) {
    __float128 ans=0;
    for (int i=0;i<x.size();i++) ans+=x[i]*1.0/(i+1);
    return ans;
}
int main()    {
    scanf("%d%d",&n,&m);
    quick[0]=ONE;
    quick[1]=ploy(2,0);
    quick[1][0]=1;quick[1][1]=-1;
    for (int i=2;i<=m;i++) quick[i]=quick[i-1]*quick[1];
    for (int i=1;i<=m;i++) {
        int x,y;
        scanf("%d%d",&x,&y);
        x--,y--;
        e[i*2-1]=(edges){x,y};
        e[i*2]=(edges){y,x};
    }
    b[1]=1;f[1]=ONE;
    dp((1<<n)-1);
    ploy ans=ONE-f[(1<<n)-1];
    printf("%.6lf\n",double(cal(ans)));
    return 0;
}

 

posted @ 2015-04-12 22:19  New_Godess  阅读(936)  评论(0编辑  收藏  举报