A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 酱油 于 2016-2-13 20:16 编辑

过年了,黑马为学生们举行了一次抽奖活动,规则如下:
      首先,所有参加抽奖的的人都将一张写有自己名字的字条放入抽奖箱中;
      然后,待所有字条加入完毕,每人从箱中取一个字条;
      最后,如果取得的字条上写的就是自己的名字,那么就表示中奖了!
但是。悲剧的是,最后却发现现场的所有人都没有中奖,。。。
好的,那么问题来了,请用编写程序计算一下,发生这种情况的概率是多少?
问题要求:用键盘输入一个整数P表示参加抽奖活动的人数。
          程序运行,输出结果为所有人都没中奖的概率。用百分号表示,四舍五入保留两位小数。
          如输入2,结果运行输出答案应该是50.00%

答题要求:1、写出解题思路。
                  2、运行截图,输出结果按照题中要求
                  3、不得百度、抄袭,如有发现,,,没有分哦
                   4、答对经过审核者,可获得10个黑马币




33 个回复

正序浏览
666666666666666666666
回复 使用道具 举报
本帖最后由 j6819236 于 2016-2-17 10:45 编辑

概率公用程序直接写上去貌似有点简单,所以用递归模拟了下这个过程。
根据概率定义写的,算出事件总数sum,再算出每个人都抽不到自己的事件数signal, signal/sum就是所求概率
假设有n个人,n就代表第n个人的名字,可以用集合模拟,只要第n个人不抽到数字n也就是不抽到自己,
例如有4个人, 3,2,1,0 对应抽到的名字 0,1,2,3这就算一种情况,用递归先抽第n个人的卡片,接着n-1,直到第1个人
。但是貌似这样内存有点吃不消,有人能帮忙修改下吗,实在没办法优化。
  1. package com.heima;

  2. import java.util.ArrayList;
  3. import java.util.Scanner;

  4. /*问题要求:用键盘输入一个整数P表示参加抽奖活动的人数。
  5. 程序运行,输出结果为所有人都没中奖的概率。用百分号表示,四舍五入保留两位小数。
  6. 如输入2,结果运行输出答案应该是50.00%*/

  7. //总的思路,就使用集合模拟抽取过程,用集合索引n对应第n个人,集合中元素则装载着对应卡片
  8. public class Test10 {
  9.         // 装载抽不到自己名字卡片的组合集合
  10.         static ArrayList<Integer> list = new ArrayList<>();

  11.         public static void main(String[] args) {
  12.                 Scanner sc = new Scanner(System.in);
  13.                 System.out.println("请输入参加活动人数:");
  14.                 while (true) {
  15.                         int n = sc.nextInt();
  16.                         ArrayList<Integer> arr = new ArrayList<>();
  17.                         // 模拟抽奖盒子有n张卡片,把n张卡片一一对应添加进集合arr,从0开始
  18.                         init(arr, n);
  19.                         // 是否打印所有抽不到自己名字卡片的排列组合
  20.                         System.out.println("请选择是否打印结果('1'为'是'):");
  21.                         int print = sc.nextInt();
  22.                         // 计算所有人都抽不到自己名字卡片概率并精确到指定精度
  23.                         double pro = (double) eventNotSelf(arr, print) / (double) eventSum(arr);
  24.                         StringBuffer strPro = new StringBuffer(String.valueOf(Math.round(pro * 10000)));
  25.                         System.out.println("所有人都没中奖概率:" + strPro.insert(2, ".") + "%");
  26.                 }
  27.         }

  28.         // 模拟把n张卡片装进抽奖盒子
  29.         public static void init(ArrayList<Integer> arr, int n) {

  30.                 for (int i = 0; i < n; i++) {
  31.                         arr.add(i);
  32.                 }
  33.         }

  34.         // 计算n个人不放回地从盒子中抽1张卡片事件数总和
  35.         public static int eventSum(ArrayList<Integer> arr) {
  36.                 int count = 0;
  37.                 // 卡片全抽完,事件数总和加1
  38.                 if (arr.size() == 1) {
  39.                         return 1;
  40.                 }
  41.                 // 模拟卡片抽取,第arr.size个人可以抽取盒子当前任意卡片,每种可能都要计算
  42.                 for (int i = 0; i < arr.size(); i++) {
  43.                         // 第arr.size个人拿出写着arr.get(i)名字卡片
  44.                         int temp = arr.get(i);
  45.                         // 盒子中去除此卡片
  46.                         arr.remove(i);
  47.                         // 第arr.size-1个人拿盒子中剩余的卡片,事件总数累加
  48.                         count = count + eventSum(arr);
  49.                         // 回到第arr.size个人,他还有可能抽写着非arr.get(i)名字卡片,所以放回arr.get(i)卡片,抽其他人名字卡片
  50.                         arr.add(i, temp);
  51.                 }
  52.                 // 返回事件总和数
  53.                 return count;
  54.         }

  55.         // 抽不到自己名字卡片的事件总和数,print=1打印每个人对应抽到的卡片
  56.         public static int eventNotSelf(ArrayList<Integer> arr, int print) {
  57.                 int count = 0;
  58.                 // 模拟卡片抽取,第arr.size个人可以抽取盒子当前任意非自己名字卡片,每种可能都要计算
  59.                 for (int i = 0; i < arr.size(); i++) {
  60.                         // 第arr.size个人拿出写着arr.get(i)名字卡片
  61.                         int temp = arr.get(i);
  62.                         // 第arr.szie个人没拿到写着自己名字的卡片
  63.                         if (temp != arr.size() - 1) {
  64.                                 // 装载入list
  65.                                 list.add(temp);
  66.                                 // 如果是最后一个人,符合事件要求,每个人都没拿到自己名字卡片,事件数总和加1
  67.                                 if (arr.size() == 1) {
  68.                                         // 是否打印每个人抽的的卡片
  69.                                         if (print == 1)
  70.                                                 System.out.println(list);
  71.                                         count = 1;
  72.                                         // 如果不是最后一个人,则接着抽取盒子中卡片
  73.                                 } else {
  74.                                         // 首先从盒子中抽走arr.get(i)名字卡片
  75.                                         arr.remove(i);
  76.                                         // 第arr.size-1个人接着抽盒子剩余卡片,事件数总和累加
  77.                                         count = count + eventNotSelf(arr, print);
  78.                                         // 因为 第arr.size个人还有可能抽到非arr.get(i)名字卡片,所以放回卡片重新抽下一张
  79.                                         arr.add(i, temp);
  80.                                 }
  81.                                 // 进入下一种情况,清除上一种情况
  82.                                 list.remove(list.size() - 1);
  83.                         }
  84.                 }
  85.                 return count;

  86.         }

  87. }
复制代码


回复 使用道具 举报
酱油 发表于 2016-2-15 21:30
我让洋葱给你分了。。。

{:2_32:}楼主你真棒!哈哈。
回复 使用道具 举报
本帖最后由 yindalei00 于 2016-2-16 00:14 编辑

都未中奖概率   初中学的还给老师了        占楼编辑概率是硬伤 初学不易
import java.util.Scanner;
public class Test1 {
        public static void main(String[] args) {
                System.out.println("请输入参与抽奖的人数");
                Scanner PP=new Scanner(System.in);
                float p=PP.nextFloat();
                double chance;
                //double chance= "!!!求中奖概率!!!!!";
                chance*=100;       
                System.out.printf("所有人都没中奖的概率为%.2f",chance);
                System.out.println("%");
                }
}

回复 使用道具 举报
wusiyi 发表于 2016-2-13 23:07
楼主,这个公式也做出来了,分就给我把。啊哈哈。

我让洋葱给你分了。。。
回复 使用道具 举报
boboyuwu 发表于 2016-2-13 21:17
代码:
import java.util.Scanner;
class GaiLv

啊哈哈,这想法是错的,我之前也是这么想的。
回复 使用道具 举报
wusiyi 发表于 2016-2-13 22:23
我网上找了一下公式,发现确实是你的那个答案,不过21的时候并不是趋近于0。我也想通了我原来的想法哪里出 ...

楼主,这个公式也做出来了,分就给我把。啊哈哈。
回复 使用道具 举报
boboyuwu 发表于 2016-2-13 21:57
反正你出概率的题我就不想做了 高中概率没及格过

你都那么多分了,不做也行了。赏我点{:2_38:}
回复 使用道具 举报

我网上找了一下公式,发现确实是你的那个答案,不过21的时候并不是趋近于0。我也想通了我原来的想法哪里出问题了,哈哈。
回复 使用道具 举报
反正你出概率的题我就不想做了 高中概率没及格过
回复 使用道具 举报
代码:
import java.util.Scanner;
class GaiLv
{
        public static void main(String []args) {
                System.out.println("请输入参与抽奖的人数");
                Scanner scanner=new Scanner(System.in);
        int num=scanner.nextInt();
                float n=num;
                float g=0;
                float sum=0;
        for(float i=0;i<num;i++) {
                  g=1-1/(n-i);
                  sum=sum+g;
                }
        }
}


思路

1.思路
假设总共有n个人抽奖,第一个抽不中自己的概率是1-(1/n),第二个抽不中自己的概率是1-(1/n-1),第三个就是
1-(1/n-2)...第n-1个抽不中概率是
1/2,第n个抽不中概率是0
最后所有求到的概率相加

点评

。。。。。这样不行吧,,,  发表于 2016-2-13 21:29

评分

参与人数 1黑马币 +2 收起 理由
洋葱头头 + 2

查看全部评分

回复 使用道具 举报 1 0
我再想想看看。。。
回复 使用道具 举报
酱油 发表于 2016-2-13 20:54
因为这种问题当人数多了以后,所有人不中奖的发生概率就会变小,我这里是保留的2位小数,所以7以后基本变 ...

关键是20的时候还是36%,到21就趋近于0%,这不科学!

点评

不知道函数里的突变么?  发表于 2016-2-13 21:26
回复 使用道具 举报
wusiyi 发表于 2016-2-13 20:33
你的结果中,从7开始概率就没变了耶。。。

因为这种问题当人数多了以后,所有人不中奖的发生概率就会变小,我这里是保留的2位小数,所以7以后基本变化都不大了。给你看一张另外的截图,,基本到了20以后概率就趋近于0了,,,(还有这道题,在数学里面是 属于 错排列问题,,有一个公式很简单解决这类问题。。。。是不是感觉被坑了?。、。。

Z~CK}P{CG~GK9P5D@DAYOQ6.png (37.57 KB, 下载次数: 51)

Z~CK}P{CG~GK9P5D@DAYOQ6.png
回复 使用道具 举报
wusiyi 发表于 2016-2-13 20:38
嗯,楼主,概率确实是1/P.
如果有P人,那么第一个人抽不中的概率为P-1/P;
第二个人抽的时候只剩下P-1,所 ...

,,,,你认真看了么?说的是所有人都不中奖的概率 ,,你觉得会是1/P ?你也跟着他一起来逗我了?
回复 使用道具 举报
youngrivers 发表于 2016-2-5 01:15
中奖 概率是1/P,你在逗我,这个有什么好编程计算的

嗯,楼主,概率确实是1/P.
如果有P人,那么第一个人抽不中的概率为P-1/P;
第二个人抽的时候只剩下P-1,所以第二个人抽中的概率为P-1-1/P-1;
.....
然后倒数第二个人抽的时候1/2;
所以就是(P-1)!/P!
所以就是1/P。
楼主给分呗。
回复 使用道具 举报 0 1
酱油 发表于 2016-2-13 19:16
没怎么看懂你的思路,,不过,我验证了一下你的结果,是错的。给你看一下我测试的数据吧,这是我原来在oj ...

你的结果中,从7开始概率就没变了耶。。。
回复 使用道具 举报
wusiyi 发表于 2016-2-13 17:38
附件Test.zip直接改名成Test.java。
下面是代码和截图,附件中也是代码和截图。
楼主快赏我!!!

权限取消了
回复 使用道具 举报
酱油 发表于 2016-2-13 19:16
没怎么看懂你的思路,,不过,我验证了一下你的结果,是错的。给你看一下我测试的数据吧,这是我原来在oj ...

我把权限取消了。。
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马