递推学习笔记
递推其实就是根据已有的条件推出答案,比较经典的递推有斐波那契数列。
我们设\(F(n)\)为数列第\(n\)个数。
\(F(x) = F(x-1) + F(x - 2)\)
其中边界条件为\(F(1)=1\ F(2)=1\)
这就是一种递推操作。另外的比较著名的递推还有:汉诺塔、\(Catalan\)数......但这些题目都不算\(dp\),动态规划比这些要复杂多了。
然后递推和递归也有很大的关系,刚开始大家都会先写递归(递归好写一些),而递推的话会更好,还会防止爆栈问题。
现在我们根据一道例题来深入理解递推操作:
求多少个\(n\)个数的排列\(A\) ,满足对于任意的\(i(1 ≤ i ≤ n)\) 使\(A_i ≠ i\)。
我们考虑递推
首先容易推出来\(f(1)=0\)因为一个数的全排列只有一个,不可能错排
然后\(f(2)=1\) 两数相反就可以
从\(3\)开始推,我们先考虑\(n\)个数分别放在\(n\)个位置有\(n\)种方法,不放在原位置就是\(n-1\)种方法
然后看两种情况
1.数\(x\)放在原位置上,那那么除\(l\)外的\(n − 1\)个数的方法就有\(f(n-2)\)种方案(其他数字放在不同的位置)
2.数\(x\)不放在原位置上,那其他数就乱放,方案数为\(f(n-1)\)
所以递推式为
\(f(n)=(n-1)*(f(n-1)+f(n-2)) (n>2)\)
代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
unsigned long long a[25];
int main()
{
int n;
cin >> n;
a[1] = 0;
a[2] = 1;
for (int i = 3; i <= n; i ++ )
a[i] = (i - 1)*(a[i - 1] + a[i - 2]);
cout << a[n];
return 0;
}

浙公网安备 33010602011771号