牛客网-年会抽奖

1 : 题目描述

链接:https://www.nowcoder.com/questionTerminal/610e6c0387a0401fb96675f58cda8559
来源:牛客网
 

2 : 解题思路

大体思路 : 不获奖的概率 == 所有人均未拿到属于自己的名牌 / 所有名牌的排列组合的情况 * 100%
我们可以分别求出分子与分母也就相当于求出了结果
分子 : 所有人均未拿到属于自己的名牌
      假设一共有n个人,第一个人没有拿到自己的名牌,
      则第一个人有可能拿到的就是剩余的n-1个人中随机一个人的名牌,故有n-1中情况.
      而第二个人拿到的名牌情况又可以分为两种 : 
          1.他拿到了第一个人的名牌 : 
          此时由于前两个人相互拿到了对方的名牌,
          故剩余的情况相当于剩余的n-2个人均未拿到自己名牌的所有组合,
          则f(n) = (n-1) * f(n-2);
          2.他未拿到第一个人的名牌 :
          此时的情况就相当于是剩余n-1个人均未拿到自己名牌的所有组合,
          则f(n) = (n-1) * f(n-1);
      所有的组合就等于这两种情况的和
      则f(n) = (n-1) * f(n-2) + (n-1) * f(n-1) = (n-1) * (f(n-2) + f(n-1));
分母 : 所有名牌的排列组合情况
      假设一共有n个人
      第一个人有n个种选择方式,每种选择都要考虑上,
      第二个人有n-1种选择方式(第一个人拿走了一个)
      ......
      不难看出,所有组合的情况==n * (n-1) * (n-2) * ..... * 2 * 1

3 : 实现代码(代码测试过,没问题)

3.1 : 递归

import java.util.Scanner;

public class Main{
    public static void main(String[]args){
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
            int n = sc.nextInt();
            double x = getUp(n);//得到分子
            double y = getDown(n);//得到分母
            double ret = x/y*100;
            System.out.printf("%.2f",ret);
            System.out.println("%");
        }
    }

    private static double getDown(int n) {
        double ret=1;
        for (int i = 1; i <=n ; i++) {
            ret*=i;
        }
        return ret;
    }

    private static double getUp(int n) {
        if(n<2) return 0;
        if(n==2) return 1;
        return (n-1) * (getUp(n-1) + getUp(n-2));
    }
}

3.2 : 迭代

import java.util.Scanner;

public class Main{
    public static void main(String[]args){
        Scanner sc = new Scanner(System.in);
        //该数组代表有i个人的时候所有人均未获奖的概率
        double[]ret = new double[21];//输入数据范围 : 2--20
        ret[2] = 50.00;
        //该数组代表有i个人的时侯所有人均未拿到自己的号码牌的所有情况
        double[]arr = new double[21];
        arr[2] = 1;
        long t = 2;//注意这里要使用long,否则会溢出
        for (int i = 3; i < 21; i++) {
            arr[i] = (i-1) * (arr[i-1]+arr[i-2]);//递推公式
            t*=i;//求阶乘
            ret[i] = (double) arr[i]/t*100;
        }
        while(sc.hasNext()){
            int n = sc.nextInt();
            System.out.printf("%.2f",ret[n]);
            System.out.println("%");
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值