错排公式的应用JLOJ2427(递推和递归之间的转化)

题目:一个晚会活动,所有参加晚会的人把自己名字放入抽奖箱中,然后每个人从箱中取出一张字条,如果字条上写的是自己名字,则视为中奖。输入人数,求没有人中奖的概率。
(题目来源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以后,会出现栈不够用的情况。
到了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;
}

完美运行√,弄明白递推递归之间的关系,把函数传递的参数作为循环判定。这样能快的把递推转化为递归

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值