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\n",sum/tot);
    }
    return 0;
}

hdu4921 Map,布布扣,bubuko.com

时间: 2024-10-13 02:03:29

hdu4921 Map的相关文章

hdu4921 Map(状压统计)

hdu4921 Map(状压统计) 题意:有10条长度不超过1000链,链上的节点有权值.我们从这些节点中选出一些节点来,若要选节点u,则u的前继都得被选进去.对于某一种选定的情况,我们能获得的权值为,选定的节点的权值和,以及一些附加值.附加值的求法为,对于每条链的同一深度的点,若选定的点的个数超过1,那么会得到的附加值为(si*xi/ci),其中si表示该层选中的点的权值和,xi为该层选中的点的个数,ci为该层的总点数.问,对于所有的选择情况,能得到的权值期望会是多少? 解法:很直观的一点,期

python练习之map()和reduce()函数

利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字.输入:['adam', 'LISA', 'barT'],输出:['Adam', 'Lisa', 'Bart']: 1 def normalize(name): 2 name=name.lower() 3 name=name[0].upper()+name[1:] 4 return name 5 6 7 8 9 10 # 测试: 11 L1 = ['adam', 'LISA', 'barT'] 12 L2 = l

ArrayList以及Map小练

ArrayList常用方法 public static void main(String[] args) { List list = new ArrayList(); List list1 = new ArrayList(); for (int i = 0; i < 5; i++) { list.add(i, "string"+i);//add(E e)向某集合的尾部追加 list1.add(i, "string"+(i+10)); } List list2

python之Map函数

# map()函数使用举例 # 功能:map()接受一个函数f和一个或多个list,将f依次作用在list的每个元素,得到一个新的列表 # 语法:map(方法名,列表,[列表2]) # 注意:map()函数的返回值需要强制转换成list类型,且不改变原列表值 list_1 = [1, 2, 3, 4, 5] list_2 = [1, 2, 3, 4, 5] # 单个参数 def double_function(number): return number * 2 list_result = li

14:Challenge 7(map大法好)

总时间限制:  10000ms 单个测试点时间限制:  1000ms 内存限制:  262144kB 描述 给一个长为N的数列,有M次操作,每次操作是以下两种之一: (1)修改数列中的一个数 (2)求数列中某个值出现了多少次 输入 第一行两个正整数N和M.第二行N的整数表示这个数列.接下来M行,每行开头是一个字符,若该字符为'M',则表示一个修改操作,接下来两个整数x和y,表示把x位置的值修改为y:若该字符为'Q',则表示一个询问操作,接下来一次整数x,表示求x这个值出现了多少次. 输出 对每一

数据结构Set和Map

一.数据结构 Set 集合的基本概念:集合是由一组无序且唯一(即不能重复)的项组成的.这个数据结构使用了与有限集合相同的数学概念,应用在计算机的数据结构中.  特点:key 和 value 相同,没有重复的 value.ES6 提供了数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. 1. 如何创建一个 Set const s = new Set([1, 2, 3]); 2.属性 console.log(s.size); // 3 3.Set 类的方法 --set.add(v

spark 教程三 spark Map filter flatMap union distinct intersection操作

RDD的创建 spark 所有的操作都围绕着弹性分布式数据集(RDD)进行,这是一个有容错机制的并可以被并行操作的元素集合,具有只读.分区.容错.高效.无需物化.可以缓存.RDD依赖等特征 RDD的创建基础RDD 1.并行集合(Parallelized Collections):接收一个已经存在的Scala集合,然后进行各种并行运算 var sc=new SparkContext(conf) var rdd=sc.parallelize(Array(2,4,9,3,5,7,8,1,6)); rd

JSON字符串-赋张最初接触后台从map转json的方法

**************************************** json数组: ****************************************************** 后台传回前台 和 前台传回后台的都是json字符串 ****************************************************** 将java中的map,list等转成json格式 (map转成JSONObject   list转成JSONArray) 前者的类

数组中出现最多的数,以及接口 Map.Entry&lt;K,V&gt;

1 package test.tools; 2 3 import java.util.Collection; 4 import java.util.Collections; 5 import java.util.HashMap; 6 import java.util.Map; 7 8 public class TestArr { 9 10 public static void MaxCount(int[] arr) { 11 Map<Integer, Integer> map = new Ha