题目:一个晚会活动,所有参加晚会的人把自己名字放入抽奖箱中,然后每个人从箱中取出一张字条,如果字条上写的是自己名字,则视为中奖。输入人数,求没有人中奖的概率。
(题目来源JLOJ2427)
首先读题,通过数学理解,能明白该题应该使用错排问题。
百度百科详解:https://baike.baidu.com/item/错排公式/10978508?fr=aladdin#1
考虑一个有n个元素的排列,若一个排列中所有的元素都不在自己原来的位置上,那么这样的排列就称为原排列的一个错排。
一开始第一反应直接递归
#include "stdafx.h"
#include "iostream"
#include <stdlib.h>
#include <math.h>
using namespace std;
double count1(double n);
double sum1(double k);
int main()
{
double m, i;
cin >> i;
m = (count1(i) / sum1(i)) * 100;
cout << m << "%" << endl;
}
double count1(double n)
{
if (n == 1){
return 0;
}
if (n == 2) {
return 1;
}
else{
return (n - 1)*(count1(n - 1) + count1(n - 2));
}
}
double sum1(double n)
{
if (n == 0)
{
return 1;
}
else
{
return n * sum1(n - 1);
}
}
递归后得意洋洋的进行测试,
发现当人数在9以后,会出现栈不够用的情况。
进行优化,将递归改为递推
double count2(int n)
{
int i = 2;
if (n > 2)
{
while (i < n)
{
a[i] = i * (a[i - 2] + a[i - 1]);
i++;
}
return a[i - 1];
}
return a[n - 1];
}
double sum2(int n)
{
int i, k1 = 1;
for (i = n; i > 0; i--)
{
k1 *= i;
}
return k1;
}
完美运行√,弄明白递推递归之间的关系,把函数传递的参数作为循环判定。这样能快的把递推转化为递归