递推是什么?
递推的基本模型有:
基本模型来开会
1.Fibonacci
题目直通车
简介
斐波纳契数列原型:
1, 1, 2, 3, 5, 8, 13······
据说,是斐波纳契探究兔子问题的时候鼓捣了这个数列
AC代码亮相:
#include
#include
int a[25];
int main() {
freopen ("rabbit.in", "r", stdin);
freopen ("rabbit.out", "w", stdout);//文件输入输出
int n;
scanf("%d", &n);
a[1] = a[2] = 1;初始化
for (int i = 3; i <= n; i++) {
a[i] = a[i - 1] + a[i - 2];//用递推式递推
}
printf("%d", a[n]);
return 0;
}
2.Hanoi塔
题目直通车
简介
一个很著名的益智游戏,汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。(注:百度资料)
我们先来找个归路规律:
个数 : 1 2 3 4 ······
次数 : 1 3 7 15 ······
明白了?
次数有一个特点:等于 2 ^ 个数 - 1。
于是,代码简单明了:
#include
#include
int main() {
int n;
scanf("%d", &n);
long long ans = 1;//保险,防止溢出
for (int i = 1; i <= n; i++) ans *= 2;计算
printf("%lld", ans - 1);
return 0;
}
3.分割平面
题目直通车
我们依然是先来找一下规律吧
曲线数 1 2 3 4 ······
平面数 2 4 8 14 ······
结果显而易见,加2,加4, 加6······
这就真成一道小学题了
AC代码如下
#include
#include
int main() {
int n;
scanf("%d", &n);
long long b = 2;
long long sum = 2;//保险,防止溢出
for (int i = 2; i <= n; i++) {
sum += b;
b += 2;
}//递推
printf("%lld", sum);
return 0;
}
由此可见,递推的难点就是找递推式。一旦找出来,就可以轻而易举地解答此水题了
4.Catalan数
题目直通车
卡特兰数又称卡塔兰数,卡特兰数是组合数学中一个常出现在各种计数问题中的数列。以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)的名字来命名。(注:百度资料)
又是一个数列,如下:
1,1,2,5,14,42,132,429 ······
(注:此处从第0项开始)
是不是比上面的斐波纳契数列难得多?是不是还没有思路?没事,要是你全部都会,来学校干什么呢
递推式奉上:h(n)= h(0) * h(n-1) + h(1) * h(n-2) + ... + h(n-1)h(0) (其中n>=2)
很复杂?
经过错位相减的方法化简以后,是这样的:
h(n) = h(n-1) * (4n-2) / (n+1)。其中(n>1), h(0)=h(1)=1
于是,代码出炉:
#include
#include
long long h[35];
int main() {
h[0] = h[1] = 1;
int n;
scanf("%d", &n);
n -= 2;//为什么要减2我也不知道,减了就对了 -_-
for (int i = 2; i <= n; i++) {
h[i] = h[i - 1] * (4 * i - 2) / (i + 1);//递推
}
printf("%lld", h[n]);//注意占位符,输出
return 0;
}
5.第二类stirling数
题目直通车
简介
题目讲解
but他们说GM说没用
话不多说,AC代码如下:
#include
#include
#include
#include
using namespace std;
const int MAXN = 30;
long long a[MAXN][MAXN];
int main() {
int n, m;
scanf("%d %d", &n, &m);//n是球数,m是盒子数
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= m; j++) {
if (j == 1) a[i][j] = 1;//若只有一个盒子,就只有一种方法
else if (i == j) a[i][j] = 1;//若盒子数与球数相等,也就一种方法
else if (j == 0) a[i][j] = 0;//没盒子咋放
else if (i < j) a[i][j] = 0;//盒子比球多,咋放嘛
else if (i > j) {
a[i][j] = j * a[i - 1][j] + a[i - 1][j - 1];递推
}
}
}
printf("%lld", a[n][m]);
return 0;
}