题面
时间限制: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;
}