例题一 错排问题:link
题目描述
求多少n个数的排列 ,满足对于任意的 。
输入格式
一个整数 n。
输出格式
一个整数,表示答案。
样例
输入样例
2
输出样例
1
数据范围与提示
对于 100 100% 100 的数据, 1 < = n < = 20 1<=n<=20 1<=n<=20。
思路:
设f(n)表示n个数合法的错排方案数
- 我们考虑第n个元素,把它放在一个位置k上,共有n-1种放法( k ≠ n k\neq n k=n,即不能放回原位)
- 考虑第k个元素,此时有两种:
(1)把第k个元素放在位置n上,那么对于除n以外的n-1个元素,
由于第k个元素以固定放在位置n上,所以剩下的n-2的数错排,即有f(n-2)种放法
(2)不把第k个元素放在位置n上,那么对于除n以外的n-1个元素错排就行了,即f(n-1)种放法
故有递推式:
f ( n ) = ( n − 1 ) ( f ( n − 1 ) + f ( n − 2 ) ) n ≥ 3 f(n)=(n-1)(f(n-1)+f(n-2)) n\geq3 f(n)=(n−1)(f(n−1)+f(n−2))n≥3
边界为:
f ( 1 ) = 0 , f ( 2 ) = 1 f(1)=0,f(2)=1 f(1)=0,f(2)=1
#include <cstdio>
#include <iostream>
#define ll long long
using namespace std;
const ll N = 25;
ll n, f[N];
int main()
{
scanf("%lld", &n);
f[1] = 0, f[2] = 1;
for(ll i = 3; i <= n; i++) f[i] = (i - 1) * (f[i - 1] + f[i - 2]);
printf("%lld", f[n]);
return 0;
}
例题二 奇怪的汉诺塔:link
题目描述:
汉诺塔问题,条件如下:
这里有 A、B、C 和 D 四座塔。
这里有 个圆盘, 的数量是恒定的。
每个圆盘的尺寸都不相同。
所有的圆盘在开始时都堆叠在塔 A 上,且圆盘尺寸从塔顶到塔底逐渐增大。
我们需要将所有的圆盘都从塔 A 转移到塔 D 上。
每次可以移动一个圆盘,当塔为空塔或者塔顶圆盘尺寸大于被移动圆盘时,可将圆盘移至这座塔上。 请你求出将所有圆盘从塔 A 移动到塔 D,所需的最小移动次数是多少。
输入格式
没有输入。
输出格式
对于每一个整数 ( 1 ≤ n ≤ 12 1\leq n\leq12 1≤n≤12),输出一个满足条件的最小移动次数,每个结果占一行。
思路:
首先我们来分析一下三根柱子的问题,
设d(n)表示三个柱子n个盘子的最优步数
先将A柱上 ( n − 1 ) (n-1) (n−1)个盘子移到B柱上,那最优的步数为d(n-1),
再将A柱上剩余的1个盘子移到C柱上,那最优步数为$1 即:d(1) $
最后将B柱上的 ( n − 1 ) (n-1) (n−1)个盘子移到C柱上,最优步数为 d ( n − 1 ) d(n-1) d(n−1)
故有递推式:
d ( n ) = 2 × d n − 2 + 1 n > 1 d(n)=2\times d_{n-2}+1\;\;\;\;n>1 d(n)=2×d