目录
一、题目
二、思路
1、错排问题
2、n 的阶乘
3、输出格式要求
三、代码
一、题目
题目:年会抽奖 题目链接:年会抽奖
今年公司年会的奖品特别给力,但获奖的规矩却很奇葩:
1. 首先,所有人员都将一张写有自己名字的字条放入抽奖箱中;
2. 待所有字条加入完毕,每人从箱中取一个字条;
3. 如果抽到的字条上写的就是自己的名字,那么“恭喜你,中奖了!”
现在告诉你参加晚会的人数,请你计算有多少概率会出现无人获奖?
输入描述:
输入包含多组数据,每组数据包含一个正整数n(2≤n≤20)。输出描述:
对应每一组数据,以“xx.xx%”的格式输出发生无人获奖的概率。
输入
2
输出
50.00%
二、思路
需要计算没有人获奖的概率,则需要两个数值,一个是没有人获奖的情况的数量(错排问题),一个是所有的情况(排列组合)的数量。
1、错排问题
用A、B、C……表示写着n位友人名字的信封,a、b、c……表示n份相应的写好的信纸。把错装的总数为记作D(n)。假设把a错装进B里了,包含着这个错误的一切错装法分两类:
- b装入A里,这时每种错装的其余部分都与A、B、a、b无关,应有D(n-2)种错装法。
- b装入A、B之外的一个信封,这时的装信工作实际是把(除a之外的)n-1份信纸b、c……装入(除B以外的)n-1个信封A、C……,显然这时装错的方法有D(n-1)种。
总之在a装入B的错误之下,共有错装法D(n-2)+D(n-1)种。
a装入C,装入D……的n-2种错误之下,同样都有D(n-1)+D(n-2)种错装法。因此D(n)=(n-1)[D(n-1)+D(n-2)]
D(n) = (n-1) [D(n-2) + D(n-1)]
特殊地,D(1) = 0、 D(2) = 1
公式推导:
2、n 的阶乘
分母是所有抽奖的情况,即所有总数的排列组合,即 n的阶乘。利用数组,每次进行累乘即可。
3、输出格式要求
要使用“xx.xx%”的格式输出,因此我们使用 printf格式化输出。
%f:输出小数点类型
%.2f:指定输出小数点后两位。
输出中还要有 %,因此要使用 %% 来输出 %。
三、代码
import java.util.Scanner;
/**
* Created with IntelliJ IDEA.
* Description:
* User: WangWZ
* Date: 2023-04-14
* Time: 13:39
*/
public class Main {
public static void main(String[] args) {
//arr存放错装数
//注意有20个数,但是我们数组里的0是不用的
//因此要创建一个21个元素的数组
long[] arr = new long[21];
arr[0] = 0;
arr[1] = 0;
arr[2] = 1;
//sum 存放总的排列组合个数
long[] sum = new long[21];
sum[0] = 0;
sum[1] = 1;
sum[2] = 2;
for (int i = 3; i <= 20; i++) {
arr[i] = (i - 1) * (arr[i - 1] + arr[i - 2]);
sum[i] = i * sum[i - 1];
}
Scanner sc = new Scanner(System.in);
while(sc.hasNextInt()) {
int n = sc.nextInt();
System.out.printf("%.2f%%\n",100.0*arr[n]/sum[n]);
}
}
}