1021谷学长的童年

文章讲述了如何运用容斥原理和位元素枚举的方法,计算在给定每种卡片出现概率的情况下,集齐所有不同卡片所需的平均干脆面购买量,给出了具体算法实现和示例输入输出
摘要由CSDN通过智能技术生成

题目描述

小时候,谷学长买了很多干脆面,因为一旦集齐所有类型的卡片就有大奖可拿。
谷学长很聪明的意识到要想集齐全套卡片就得买相当多的干脆面,为了尽可能的省钱,他想计算出每种类型卡片均获得一张应买干脆面的期望数目。

输入描述

每个测试用例的第一行包含一个N(1 <= N <= 20), 表示干脆面里可能放置N种类型的卡片,第二行有N个数p1, p2, ..., pN, (p1 + p2 + ... + pN <= 1), 表示中到对应类型卡片的概率。
注意每袋干脆面最多只有一张卡片。

输出描述

对于每组测试用例,输出集齐N张不同类型的卡片所买干脆面的期望数目。结果保留三位有效数字。

样例输入
1
0.1
2
0.1 0.4
样例输出
10.000
10

规律:使用容斥原理+位元素枚举

假设有3个元素,abc
那么他们的全部就是
a+b+c-ab-ac-bc+abc
再往下推会发现
偶数个元素如ab是被减的
奇数个元素如abc是被加的
使用(i&(1<<j))!=0以按位与进行二进制判断组合中元素的个数,当所有组合子集循环完毕,最后结果便得出。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
            double answer=0;
            int n = sc.nextInt();   
            double a[] = new double[n];
            for(int i=0;i<n;i++){
                a[i] = sc.nextDouble();//将读取的数据存储到数组中
            }	

            for(int i=0;i<(1<<n);i++){   //对每组排列组合子集进行判断
                double sum = 0;
                int counter=0;
                for(int j=0;j<=n;j++){  
                    if((i&(1<<j))!=0){  //判断子集包含元素
                        sum+=a[j];
                        counter++;
                    }
                }

                if(counter%2==0&&sum!=0){   //元素为偶数相减
                    answer-=1/sum;
                }else if(counter%2!=0&&sum!=0){  //元素为奇数相加
                    answer+=1/sum;
                }

            }

            System.out.printf("%.3f\n",answer);

        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值