今年公司年会的奖品特别给力,但获奖的规矩却很奇葩:
1. 首先,所有人员都将一张写有自己名字的字条放入抽奖箱中;
2. 待所有字条加入完毕,每人从箱中取一个字条;
3. 如果抽到的字条上写的就是自己的名字,那么“恭喜你,中奖了!”
现在告诉你参加晚会的人数,请你计算有多少概率会出现无人获奖?
输入包含多组数据,每组数据包含一个正整数n(2≤n≤20)。
对应每一组数据,以“xx.xx%”的格式输出发生无人获奖的概率。
2
50.00%
import java.text.DecimalFormat; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scan = new Scanner(System.in); double[] num = new double[21]; num[0] = 0.00; num[1] = 0.00; num[2] = 50.00; double[] notAward = new double[21]; notAward[0] = 0; notAward[1] = 0; notAward[2] = 1; long total = 2; for (int i = 3; i < 21; i++) { notAward[i] = (i - 1) * (notAward[i - 1] + notAward[i - 2]); total = total * i; num[i] = (double) notAward[i] / total * 100; } DecimalFormat df = new DecimalFormat(".00"); while (scan.hasNextInt()) { int n = scan.nextInt(); if (n < 0 || n > 20) { System.out.println("error"); } else { System.out.println(df.format(num[n]) + "%"); } } scan.close(); } }
//详细解说看博客:链接在回答最下边 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 sum1=factorial(n); double sum2=count(n); double result=(sum2/sum1)*100; //计算成%的形式 System.out.println(String.format("%.2f",result)+"%"); } } //计算所有人都抽不到奖的情况:错排算法 private static double count(int n) { if(n==1){ return 0; }else if(n==2){ return 1; }else { return (n-1)*(count(n-1)+count(n-2)); } } //计算阶乘:迭代写法 private static double factorial(int n) { double sum=1; while(n>1){ sum=sum*n; n--; } return sum; } //计算阶乘:递归写法 private static double factorical2(int n){ if(n==0||n==1){ return 1; } return n*factorical2(n-1); } } ———————————————— 版权声明:本文为CSDN博主「峰回路转」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_44840148/article/details/104706415
//主要是为了复习复习python的语法,题目很简单。python写起来确实要不C简单那么一点 lst = [0, 0, 1] for i in range(3,21): lst.append((i-1)*(lst[i-1]+lst[i-2])) while True: SUM = 1 try: N = int(input()) count = lst[N] while N>0: SUM *= N N -= 1 res = (1.0*count/SUM)*100 print("{0:.2f}%".format(res)) except: break
#include "stdio.h" double gener(short x) { double item = 0.5; double result = item; for (short i = 3; i <= x; i++) { item /= -i; result += item; } return result; } int main() { short n; while (~scanf("%2hd", &n)) { printf("%5.2f%%\n", 100 * gener(n)); } return 0; }
import java.util.Scanner; //代码已通过测试,还望各位牛友批评指正 public class Main{ //这道题着实让我折腾了好半天,首先要明白这是一个排列组合问题, //我们拿5来说事,首先5个人来进行抽奖,有多少种抽法? //因为是不放回抽,所以第一个人有5种抽法, //第二个人有4种抽法,依次类推 //总共就是5! 对有5的阶乘种抽法。这是分母 //那可想而知分子就是存在多少种情况每个人拿不到自己的名字。 //这里要应用错排算法。 //简单的做个介绍 //当n个编号元素放在n个编号位置,元素编号与位置编号各不对应的方法数用D(n)表示, //那么D(n-1)就表示n-1个编号元素放在n-1个编号位置,各不对应的方法数,其它类推. //第一步,把第n个元素放在一个位置,比如位置k,一共有n-1种方法; //第二步,放编号为k的元素,这时有两种情况:把它放到位置n,那么,对于剩下的n-1个元素, //由于第k个元素放到了位置n,剩下n-2个元素就有D(n-2)种方法; //第k个元素不把它放到位置n,这时,对于这n-1个元素,有D(n-1)种方法; //综上得到递推公式,可以发现可以用递归来做; //D(n) = (n-1) [D(n-2) + D(n-1)] //特殊地,D(1) = 0, D(2) = 1. //那么D(5)=4*[D(3)+D(4)];依次求得D(3)、D(4),最后D(5)=44 //所以5个人拿不到奖的概率就是44/120=36.67% //这里只是简单介绍,具体想弄明白还是去百度错排算法吧 //下面看代码 public static float count(int n) { //这个函数用来得到有多少种可能,每个人拿不到自己的名字, //也就是得到分子 if(n==1){ //n=1的时候返回0 return 0; } if(n==2){ //n=2的时候返回1 return 1; }else{ //否则就递归。 return (n-1)*(count(n-1)+count(n-2)); } } //下面的函数用来求阶乘,也是递归,最后得到分母 public static float probability(int n){ if(n==0){ //0的阶乘等于1,不用多说吧 return 1; }else{ //阶乘表示,进行递归 return n*probability(n-1); } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); do { int n = sc.nextInt(); //将得到的分子分母进行相除,就可以得到概率了。 float result = (count(n)/probability(n))*100; System.out.println(String.format("%.2f", result) + "%"); } while (sc.hasNext()); } }
#include<stdio.h> int main() { long long der[21] = { 0,0,1 }, fun[21] = { 0,1,2 }; int i, n; for (i = 3; i < 21; i++) { der[i] = (i - 1) * (der[i - 2] + der[i - 1]); fun[i] = i*fun[i - 1]; } while (~scanf("%d", &n)) { printf("%.2f%c\n", 1.0*der[n] /fun[n] * 100, '%'); } return 0; }
n个人取到的都不是自己名字的概率=n个人取到的不是自己名字的序列个数 / n个人可能抽取的所有可能性
因此分两步计算:
1.n个人可能抽取的所有结果:
2.n个人取到的都不是自己名字的序列个数:
#include<iostream> #include<cmath> using namespace std; //1.概率:n个人取到的不是自己名字的序列个数/n个人可能抽取的所有可能性 long long NotSelf(int n) { if (n == 1 ) return 0; if (n == 2) return 1; return (n - 1) * (NotSelf(n - 1) + NotSelf(n - 2)); } long long Count(int n) { double s = 1; double m = 1; for (int i = 2; i <= n; ++i) { m *= i; } return m; } int main() { int n; while (cin >> n) { double ret = (double)NotSelf(n)/Count(n); //计算概率 printf("%2.2f%%\n", ret * 100); } return 0; }
解这道题,我们需要明白什么时候才算做都不获奖
?全部都不获奖的概率如何计算
?
对于什么时候才算做都不获奖
,当然是所有人都拿到了别人的名字,没有拿到自己的名字。全部都不获奖的概率
必定是由 n个人都拿错的情况种数
除 n个人拿出的所有排列情况数
。n个人拿出的所有排列情况数
显然是n的阶乘。
n个人都拿错的情况种数
与上一道题 PAT乙级(Basic Level)练习题 发邮件 是一样的。
假设a
的名字没有被a
拿到,其他n - 1
个人都有可能拿到,即有n - 1
种情况。假设b
拿到了a
的名字,那么对于b的名字有两种情况,
第一种是b
的名字被a
拿到了,也就是a
、b
互相拿到了对方的名字,那么对于其他n - 2
个人互相拿错又是一个子问题f(n - 2)
.
第二种是b
的名字没有被a
拿到,则剩下的问题是子问题f(n - 1).
因此可得递推公式f(n) = (n - 1) * (f(n - 1) + f(n - 2))
.
最终得出公式n人都不获奖的概率h(n) = (n - 1) * (f(n - 1) + f(n - 2)) / (n!)
.
#include <iostream> (720)#include <math.h> using namespace std; int main(int argc, const char * argv[]) { int n = 0; //fTable[n]记录n个人都拿错(全不获奖)的情况种数,allTable[n]记录所有可能的组合情况n的阶乘 long long fTable[21] = {0, 0, 1}, allTable[21] = {0, 1, 2}; for (int i = 3; i < 21; ++i) { //递推计算i个人全部拿错 fTable[i] = (i - 1) * (fTable[i - 1] + fTable[i - 2]); //递推计算i的阶乘 allTable[i] = i * allTable[i - 1]; } //scanf返回值为正确输入数据的变量个数,当一个变量都没有成功获取数据时,此时返回-1 while (scanf("%d", &n) != - 1) { //注意%属于控制字符,两个连续的%%才表示真正的%字符 printf("%4.2lf%%\n", 100 * double(fTable[n]) / allTable[n]); } return 0; } ———————————————— 版权声明:本文为CSDN博主「hestyle」的原创文章,遵循 CC 4.0 BY 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://hestyle.blog.csdn.net/article/details/104688841
#include<stdio.h> char *p[]={"0%","0%","50.00%","33.33%","37.50%","36.67%","36.81%","36.79%","36.79%","36.79%","36.79%","36.79%","36.79%","36.79%","36.79%","36.79%","36.79%","36.79%","36.79%","36.79%","36.79%"}; int main(){ int n; while(scanf("%d",&n)!=EOF){ printf("%s\n",p[n]); } return 0; }
#include <iostream> #include <vector> using namespace std; int main() { int n; while (cin >> n) { vector<double> arr(n); arr[0] = 0, arr[1] = 1; for (int i = 2; i < n; i++) { arr[i] = i * (arr[i - 1] + arr[i - 2]); } double base = 1; for (int i = 1; i <= n; i++) base *= i; printf("%.2lf%%\n", arr[n - 1] / base * 100); } return 0; }
#include<iostream> using namespace std; int main() { long long d[21] = {0,0,1}; //根据参与抽奖的人数n,计算得到总的错误情况d[n] long long f[21] = {0,1,2}; //根据参与抽奖的人数n,计算得到所有的情况 n! for(int i = 3; i <= 20; i++) { d[i] = (i-1)*(d[i-1] + d[i-2]); //错排的递推公式 f[i] = i * f[i-1]; //阶乘的递推公式 } int n; while(cin >> n) { printf("%.2f%%\n",100.00*d[n]/f[n]); //用100.00来把结果处理成double,.2f保留两位小数 } return 0; }
// write your code here import java.util.*; public class Main{ private static long f(int n) { long ret = 1; for (int i = 1; i <= n; i++) ret *= i; return ret; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { int n = sc.nextInt(); //求阶乘 long h = f(n); long[] f = new long[n + 1]; f[2] = 1; for (int i = 3; i <= n; i++) { //不可能抽到自己编号的情况数为f(n)=(n-1)*(f(n - 1) + f(n - 2)) f[i] = (i - 1) * (f[i - 1] + f[i - 2]); } double ans = 100.0 * f[n] / f(n); System.out.printf("%.2f%s\n", ans, "%"); } } }
import java.util.*; public class Main{ public static long notSelf(int n){ long[] arr = new long[21]; arr[0] = 0; arr[1] = 0; arr[2] = 1; for(int i = 3;i < arr.length;i++){ arr[i] = (i - 1) * (arr[i - 1] + arr[i - 2]); } return arr[n]; } public static float fun(int n){ if(n == 0){ return 1; } float res = 1; for(int i = 1;i <= n;i++){ res *= i; } return res; } public static void main(String[] args){ Scanner sc = new Scanner(System.in); while(sc.hasNext()){ int n = sc.nextInt(); float s = (float)notSelf(n)/fun(n); System.out.printf("%2.2f%%\n",s*100); } } }
import java.util.*; public class Main { static long[] ans = new long[21]; public static void main(String[] args) { Scanner scanner = new Scanner(System.in); ans[0] = 0; ans[1] = 0; ans[2] = 1; lottery(); while (scanner.hasNext()) { int num = scanner.nextInt(); double sum1 = factorial(num); double sum2 = ans[num]; double result = (sum2 / sum1) * 100; System.out.println(String.format("%.2f", result) + "%"); } } private static double factorial(int num) { double ans = 1; while (num > 0) { ans *= num; num--; } return ans; } private static void lottery() { for (int i = 3; i < ans.length; i++) { ans[i] = (i - 1) * (ans[i - 1] + ans[i - 2]); } } }
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)); } }
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("%"); } } }
#include <stdio.h> #include <iostream> #include <vector> using namespace std; int main() { int n; while (cin >> n) { vector<long long> v(n + 1, 0); double ans = 0.0; double sum = 2.0; v[1] = 0; v[2] = 1; for (int i = 3; i < n + 1; i++) { v[i] = (i - 1) * (v[i - 1] + v[i - 2]); sum *= i; } printf("%.2f%%\n", v[n] / sum * 100.0); } return 0; }
// write your code here import java.util.*; public class Main { public static void main(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%"); } } }