• hdu4921 Map


    给最多10条链。每条链长度最大1000,链上每点有权值,每条链上按顺序,第i个点属于level[i]。

    链上后一个点能够选的前提是前面的点都选了。

    选择了一些点能够得到的分数是两部分加起来:1、所有点权和 2、leveli的点共同拥有yi个。若你选择了xi个,则得分:你选择的该层点权和*xi/yi

    问全部可能的取值组合的分数期望。


    题意太纠结了。读的好心塞,感觉思考能力都下降了。


    由于题目是求期望,所以我们须要得到,1、总方案数,2、全部取法的得分和。

    对于1,就是(每条链上点数+1)相乘-1就是了

    对于问题2,

    当中主要要解决得分规则2,因为总共最多10条链,对于每个level i ,我们能够想到用二进制记录第i层状态,枚举第i层的取法,

    这样我们的问题就变成了。我们要求每一种取法的得分数,以及在总方案数中。这样的取法占了多少种。

    这样还是比較好算的,假如第i层,有第1 3 4 6条链上能够取,你取了1 3上的第i个数。则第4 6条链最多取到第i-1个数。如果第1 3 4 6条链上总共分别有5 6 3 4个点。

    那么取1 3的所有方案数就是   (5-1)×(6-3)×min(3,i)×min(4,i) 种。由于1 3链上必须取到第i个数,第i个后面的可选,而第4 6条链仅仅能选前i-1个数,那么这样乘起来就是总方案数。

    如今主要问题都攻克了,我们就能够累加得分算出总得分,进而求期望了。

    题目的wa点有:点从0開始记数。总方案数用int会爆,直接double就能够了。



    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #include <map>
    using namespace std;
    const int maxn=10010;
    
    int vis[maxn],son[maxn],len[15],val[maxn],level[maxn],mk[maxn],list[15][1005];
    
    double cal(int a,int b)//a表示枚举到第alevel b的二进制位表示levela层可能取哪些链
    {
        double n=1,sum=0;
        int cnt=0;
        for(int i=1;i<=10;i++,b>>=1)
        {
            if(b&1)
            {
                cnt++;
                n*=(len[i]-a);
                sum+=list[i][a];
            }
            else
                n*=(min(len[i],a)+1);
        }
        return sum*((cnt>1?cnt:0)+level[a])/level[a]*n;
    }
    
    int main()
    {
        int icy,m,i,n,k,j,a,b;
        scanf("%d",&icy);
        while(icy--)
        {
            scanf("%d%d",&n,&m);
            for(i=0;i<n;i++)//注意点是从0開始编号的。!

    ! scanf("%lld",&val[i]); memset(son,-1,sizeof son); memset(vis,0,sizeof vis); while(m--) { scanf("%d%d",&a,&b); son[a]=b; vis[b]=1; } //建图记录下面: int l=1;//求链的总数 memset(mk,0,sizeof mk);//每一个level出如今哪些链中 memset(level,0,sizeof level);//level[i]的点数 //level总数:第一个level[k]==0的k memset(list,0,sizeof list);//list[i][j]第i条链的第j位置的值 memset(len,0,sizeof len);//每条链的长度 double tot=1;//分母 for(i=0;i<n;i++) { if(!vis[i]) { vis[i]=1; for(k=0,j=i;j!=-1;j=son[j],k++) { list[l][k]=val[j]; level[k]++; mk[k]+=(1<<(l-1)); } len[l]=k; tot*=(k+1); l++; } } tot-=1;//分母 double sum=0; for(i=0;level[i];i++)//枚举每一层level for(j=mk[i];j>0;j=(j-1)&mk[i])//枚举这一层取哪几条链上的全部可能 sum+=cal(i,j); printf("%.3lf ",sum/tot); } return 0; }



  • 相关阅读:
    [HAOI2016]食物链
    [TJOI2011]序列
    P2548 [AHOI2004]智能探险车
    [JSOI2008]最大数
    模板之dinic
    Excim的NOIP2017游记
    数列排序
    Car的旅行路线
    [HAOI2006]均分数据
    [luogu2210] Haywire
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/6941177.html
Copyright © 2020-2023  润新知