河南省第十四届ICPC大学生程序设计竞赛-C结对编程

题面

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld

题目描述

A公司是一家主营软件开发的公司。公司内有n名员工,编号为1到n的整数,除了1号老板外每名员工都有一个直接上级和若干个间接上级(上级的上级)。

这天A公司正在进行结对编程能力测试。为了尽量避免由于员工个人因素影响测试的结果,本次测试采用随机抽人的方式。具体方法是由公司的所有非空员工子集中等概率地取出一个子集。然后找出该子集的级别最低的共同上级作为团队指挥(1号老板的级别是最高的)。当然,该团队指挥有可能在也有可能不在该子集中,在子集中的话就参与结对编程,不在的话就只负责指挥。

由于你大学参加过ICPC比赛,编程能力比较强,公司派你写一段程序来完成这个选人的过程。但是你最近疏于编程训练,头脑不清晰,犯了个大错误。你的代码里居然真的直接等概率取出一个非空子集,却忽略了这样一个事实:选出的子集人数必须是偶数,才能安排接下来的结对编程活动!

但是事到如今也无法挽救了。你了解到公司里每个职员都有一个可以量化的权限,当职员i被选作团队指挥时,如果你的程序输出了一个合理的结果(偶数个人),他会奖励你aia_iai​元作为酬劳,反之如果你的程序输出了一个不合理的结果(奇数个人),那他会罚你aia_iai​元作为赔偿。

那么,请你为自己计算出:你期望会损失多少钱?为了避免浮点误差,请你输出期望损失的钱数×(2^n - 1)的结果,可以证明这是个整数。同时,你的输出也有可能是个负数,此时说明期望会赚到钱。

输入描述:

输出描述:

 

示例1

输入

复制3 1 1 1 2 3

3
1 1
1 2 3

输出

复制4

4

说明

对于样例,有以下情况:

选出1,指挥为1,赔偿1元

选出2,指挥为2,赔偿2元

选出3,指挥为3,赔偿3元

选出1,2,指挥为1,赚1元

选出1,3,指挥为1,赚1元

选出2,3,指挥为1,赚1元

选出1,2,3,指挥为1,赔偿1元

最终损失的期望×(2^3-1)=4

有用信息

1、一共有n个人:编号[1,n],1<=n<=200000。

2、每一个编号为[2,n]的员工有一个直接上级。

3、每个人有个权限值a[i],是其作为指挥时罚款或赚钱的数目。

4、选出的子集的人数必须为偶数才能赚钱,奇数要罚款。

5、题目要你求对于所有的非空子集,罚款的总和。

6、如果只选了一个人,那么选到的这个人就是指挥。(看样例可以知道)

7(目测这个条件不需要管)、计算期望损失的钱数乘以 (2^n - 1):输出为整数,可能为负值表示赚到钱。

思路

既然要求出所有非空子集的罚款的总和,因为不管哪个集合都能选出一个领队的人,所以就根据指挥的人选来分类,计算每个节点作为指挥的情况下,可能的期望损失或收益,再求和。

结点i作为指挥情况下可能的损失=结点i的权值*(所有子集中结点i作为指挥的奇数个数集合的个数-所有子集中结点i作为指挥的偶数个数集合的个数)

结点i的权值为a[i]

上述等式括号内部分的值=(1-该节点的直接子节点个数)。为什么?我也不知道。

AC代码

#include<iostream>
using namespace std;
const int N=2e5+5;
int cnt[N]={0};
int c[N]={0};
int main()
{
    int n;
    cin>>n;
    for(int i=2;i<=n;i++){
        int u;
        cin>>u;
        cnt[u]++;
    }
    for(int i=1;i<=n;i++) cin>>c[i];
    long long sum=0;
    for(int i=1;i<=n;i++){
        sum+=(1-cnt[i])*c[i];
    }
    cout<<sum;
}

  • 27
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值