递推学习笔记

递推其实就是根据已有的条件推出答案,比较经典的递推有斐波那契数列。

我们设\(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;
}
posted @ 2022-07-14 21:26  ljfyyds  阅读(54)  评论(1)    收藏  举报