• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
xiaoyaovo
博客园    首页    新随笔    联系   管理    订阅  订阅
年会抽奖(Java 含彩蛋)

目录

    • 题目链接
    • 基本思路
      • 错排问题
      • 思路
    • 代码展示
      • 彩蛋

题目链接

  • 牛客链接:年会抽奖
  • 题目描述:

今年公司年会的奖品特别给力,但获奖的规矩却很奇葩:

  1. 首先,所有人员都将一张写有自己名字的字条放入抽奖箱中;
  2. 待所有字条加入完毕,每人从箱中取一个字条;
  3. 如果抽到的字条上写的就是自己的名字,那么“恭喜你,中奖了!”
    现在告诉你参加晚会的人数,请你计算有多少概率会出现无人获奖?
  • 输入:

1
2
3

  • 输出

0 %
50 %
33.33%

基本思路

首先要正确理解题意,题目求解的是 求无人获奖的概率,也就是说,所有人都没有抽要自己的名字。

  • 只有一个人的时候,百分百中奖。

在这里插入图片描述

  • 两个人的时候,

  • 1 号可能拿了 2 号的纸条,那么 2 号 只能拿 1 号的纸条;

  • 1 号拿了自己的纸条,2 号也拿自己的纸条
    因此无人中奖的概率是 1 / 2 = 50 %;
    在这里插入图片描述

  • 三个人的时候

  • 1 号拿了 1 号的纸条,2 号拿了 2 号的纸条,3 号拿了 3 号的纸条;

  • 1 号拿了 1 号的纸条,2 号拿了 3 号的纸条,3 号拿了 2 号的纸条;

  • 1 号拿了 2 号的纸条,2 号拿了 1 号的纸条,3 号拿了 3 号的纸条;

  • 1 号拿了 2 号的纸条,2 号拿了 3 号的纸条,3 号拿了 1 号的纸条;

  • 1 号拿了 3 号的纸条,2 号拿了 1 号的纸条,3 号拿了 2 号的纸条;

  • 1 号拿了 3 号的纸条,2 号拿了 2 号的纸条,3 号拿了 3 号的纸条;

对应关系:

  • 1 == 1, 2 == 2, 3 == 3;
  • 1 == 1, 2 == 3, 3 == 2;
  • 1 == 2, 2 == 1, 3 == 3;
  • 1 == 2, 2 == 3, 3 == 1; 无人获奖
  • 1 == 3, 2 == 2, 3 == 1;
  • 1 == 3, 2 == 1, 3 == 2; 无人获奖
    至少有 2 / 6 = 33.33% 的概率无人获奖。

…

经过慢慢推测,这是一个 错排问题 (百度百科)

错排问题

  1. 开始有 n 张纸条,下标数字对应纸条上写的名字。

在这里插入图片描述

  1. 当 4 (代表某个人) 拿走了 k 号纸条,那么还有 n - 1 个人;

  2. 此时 k 有两种选择, 拿走 4 号纸条或者其他纸条(比如 3 号纸条);

在这里插入图片描述
我们假设 4号 没有拿到自己名字的纸条,
那么其他 n - 1 个人都有可能拿到 4 的纸条,
而剩下 n - 1 人中,k 可以拿 4 号的纸条,那么剩下 n - 2 人中又可以划分为 n - 2 个子问题;
或者拿其他纸条,那么 n - 1 人中又可以划分为 n - 1 个子问题。
因此得到 递推公式:

F(n) = (n-1) * (F(n-1) + F(n-2))

思路

  1. 求出所有能抽中的结果,也就是 求阶乘;
  2. 求出 错排的问题 的结果;
  3. 结果 = 错排结果 / 阶乘结果 。

代码展示

彩蛋

    public static void main1(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
            int n = scanner.nextInt();
            if (n == 1)
                System.out.println("00.00%");
            else if (n == 2)
                System.out.println("50.00%");
            else if (n == 3)
                System.out.println("33.33%");
            else if (n == 4)
                System.out.println("37.50%");
            else if (n == 5)
                System.out.println("36.67%");
            else if (n == 6)
                System.out.println("36.81%");
            else if (n == 7)
                System.out.println("36.79%");
            else if (n == 8)
                System.out.println("36.79%");
            else if (n == 9)
                System.out.println("36.79%");
            else if (n == 10)
                System.out.println("36.79%");
            else if (n == 11)
                System.out.println("36.79%");
            else if (n == 12)
                System.out.println("36.79%");
            else if (n == 13)
                System.out.println("36.79%");
            else if (n == 14)
                System.out.println("36.79%");
            else if (n == 15)
                System.out.println("36.79%");
            else if (n == 16)
                System.out.println("36.79%");
            else if (n == 17)
                System.out.println("36.79%");
            else if (n == 18)
                System.out.println("36.79%");
            else if (n == 19)
                System.out.println("36.79%");
            else if (n == 20)
                System.out.println("36.79%");
        }
    }

搞错了搞错了,哈哈哈哈。再来!

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
            int n = scanner.nextInt();
            float none = method(n);
            float res = none/factorial(n)*100;
            System.out.println(String.format("%.2f",res) + "%");
        }
    }

    /**
     * 动态规划错排问题
     * @param n
     * @return
     */
    public static float function(int n) {
        float[] dp = new float[n+1];
        dp[0] = 0;
        dp[1] = 0;
        dp[2] = 1;
        for (int i = 3; i <= n; i++) {
            dp[i] = (i-1) * (dp[i-1] + dp[i-2]);
        }
        return dp[n];
    }
    /**
     * 递归错排问题
     * @param n
     * @return
     */
    public static float method(int n) {
        if (n == 1) {
            return 0;
        }else if (n == 2) {
            return 1;
        }
        return (n-1) * (method(n-1) + method(n-2));
    }

    /**
     * 递归求阶乘
     * @param n
     * @return
     */
    public static float factorial(int n) {
        if (n == 1) return 1;
        return n * factorial(n-1);
    }

    /**
     * 非递归求阶乘
     * @param n
     * @return
     */
    public static float factorialI(int n) {
        int res = 1;
        while (n > 1) {
            res *= n;
            n--;
        }
        return res;
    }
posted on 2021-07-23 01:24  豆本豆红枣豆奶  阅读(24)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3