BZOJ4675 点对游戏

来源:互联网 发布:温柔强大动漫男主 知乎 编辑:程序博客网 时间:2024/06/01 21:38

根据期望的线性性(orz xuruifan,我们一定要叫线性性,不能叫可加性),期望幸运点对数等于每个幸运点对被选中的概率之和

由于每个点都是等价的,所以每个点对也是等价的,所以我们只需要计算1个点对被选中的概率,乘以点对数再乘以2(因为是有序的)即可

一个点对被选中的概率等于他在每次操作下被选中的概率之和

假设这个点对是(x,y)

对于一个人,第i次操作一定会选择一个点,x被选中的概率是1/n

如果这次选择了x,在之前的i-1次操作中,一定不会选择x,所以每次会在n-1个点中随机选一个没被选中的,所以y被选中的概率是i-1/n-1

所以一个人的第i次操作对答案的贡献是(1/n)*(i-1/n-1)*幸运点对数×2

至于如何求幸运点对数,这是点分治的经典问题,可以在O(mn log n)时间内求出

其实我们也可以用类似BZOJ4543 POI2014 HOTEL加强版的方法来优化n^2的DP,在O(nm)的时间,O(n)的空间内求出

我写的是优化DP,因为我做这道题的时候脑抽,忘了这是点分治经典问题了-_-

#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<algorithm>#include<iomanip>#include<vector>#include<stack>#include<queue>#include<map>#include<set>#include<bitset>using namespace std;#define MAXN 50010#define MAXM 1010#define ll long long#define INF 1000000000#define MOD 1000000007#define eps 1e-8struct vec{    int to;    int fro;};vec mp[MAXN*2];int tai[MAXN],cnt;int g[MAXN];int F[MAXN*8];int *f[MAXN];int *hat=F+2;int d[MAXN];int n,m;int l[MAXN];int son[MAXN];double cs[5],ans[5];int lw[MAXN];int dep[MAXN];inline void be(int x,int y){    mp[++cnt].to=y;    mp[cnt].fro=tai[x];    tai[x]=cnt;}inline void bde(int x,int y){    be(x,y);    be(y,x);}void pre(int x,int F){    int i,y;    lw[x]=x;    dep[x]=dep[F]+1;    for(i=tai[x];i;i=mp[i].fro){        y=mp[i].to;        if(y==F){            continue ;        }        pre(y,x);        if(d[y]+1>d[x]){            son[x]=y;            lw[x]=lw[y];            d[x]=d[y]+1;        }    }    for(i=tai[x];i;i=mp[i].fro){        y=mp[i].to;        if(y!=son[x]&&y!=F){            hat+=dep[lw[y]]-dep[y]+2;            f[lw[y]]=hat;            hat+=5;        }    }    if(x==1){        hat+=dep[lw[x]]-dep[x]+2;        f[lw[x]]=hat;    }}void dfs(int x,int F){    int i,j,k,y;    for(i=tai[x];i;i=mp[i].fro){        y=mp[i].to;        if(y==F){            continue ;        }        dfs(y,x);        if(y==son[x]){            f[x]=f[y]-1;            g[x]+=g[y];            for(j=1;j<=m;j++){                if(l[j]-1<=d[y]){                    g[x]+=f[y][l[j]-1];                }            }        }    }    f[x][0]=1;    for(i=tai[x];i;i=mp[i].fro){        y=mp[i].to;        if(y==F||y==son[x]){            continue ;        }        g[x]+=g[y];        for(j=0;j<=d[y];j++){            for(k=1;k<=m;k++){                if(j<l[k]&&l[k]-j-1<=d[x]){                    g[x]+=f[y][j]*f[x][l[k]-j-1];                }            }        }        for(j=0;j<=d[y];j++){            f[x][j+1]+=f[y][j];        }    }}int main(){    int i,x,y;    scanf("%d%d",&n,&m);    for(i=1;i<=m;i++){        scanf("%d",&l[i]);    }    for(i=1;i<n;i++){        scanf("%d%d",&x,&y);        bde(x,y);    }    pre(1,0);    dfs(1,0);    for(i=1;i<=n;i++){        ans[(i-1)%3+1]+=1.0/n*cs[(i-1)%3+1]*g[1]*2;        cs[(i-1)%3+1]+=1.0/(n-1);    }    for(i=1;i<=3;i++){        printf("%.2lf\n",ans[i]);    }    return 0;}  /*6 21 31 22 31 41 52 6  */


0 0
原创粉丝点击