递推算法专题
一、HDU 2802 F(N)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2802
AC代码:
#include <stdio.h>
#include <algorithm>
using namespace std;
//HDU Accepted 2802 15MS 1256K 332 B G++
//学会找找循环解
__int64 f[110000];
void init() {
int i;
f[1] = 1;
f[2] = 7;
for(i=3; i<=5000; i++)
f[i] = (f[i-2] + 3*i*i - 3*i + 1) % 2009;
}
int main() {
__int64 n, i;
init();
while(scanf("%I64d", &n), n) {
// for(i=3; i<=110000; i=i+2)//打表法找出循环节
// if(f[i] == 1)
// break;
// printf("%I64d\n", i-1);
// for(i=4; i<=110000; i=i+2)
// if(f[i] == 7)
// break;
// printf("%I64d\n", i-2);
// printf("%I64d\n",f[4018]);
printf("%I64d\n", f[n%4018]); //通过上面注释的代码得知4018为一个循环
}
return 0;
}
二、HDU 2047 阿牛的EOF牛肉串
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2047
题目大意:用E、O、F组成长度为n的字符串,且两个O不能相邻,求一共有多少种满足要求的不同的字符串。
递推公式:
a
[
n
]
=
2
×
a
[
n
−
1
]
+
2
×
a
[
n
−
2
]
a[n] = 2\times a[n-1] + 2\times a[n-2]
a[n]=2×a[n−1]+2×a[n−2]
含义:第n个字符有为O或者不为O两种情况。若第n个字符为O,则第n-1位置的字符不能为O,这样第n-2位置的字符就可以任意取,取的方法有
a
[
n
−
2
]
a[n-2]
a[n−2]种。而第n-1位置的字符可为E或F,因此需要乘2,共有
2
×
a
[
n
−
2
]
2\times a[n-2]
2×a[n−2]种;若第n个字符不为O,则第n-1位置的字符可以任意取,取的方法有
a
[
n
−
1
]
a[n-1]
a[n−1]种,又因为第n个字符可以取E或F两种,因此乘2,共有
2
×
a
[
n
−
1
]
2\times a[n-1]
2×a[n−1]种。
代码:
#include <iostream>
using namespace std;
const int MAXN = 42;
//HDU Accepted 2047 0MS 1396K 225 B G++
long long a[MAXN] = {0, 3, 8};
int main() {
int n;
for(int i=3; i<=40; i++)
a[i] = 2*a[i-1] + 2*a[i-2];
while(cin>>n) {
cout<<a[n]<<endl;
}
return 0;
}
三、HDU 2501 Tiling_easy version
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2501
题目大意:有一个大小是 2 x n 的网格,现在需要用2种规格的骨牌铺满,骨牌规格分别是 2 x 1 和 2 x 2,请计算一共有多少种铺设的方法。
递推公式:
a
n
s
[
i
]
=
a
n
s
[
i
−
1
]
+
2
×
a
n
s
[
i
−
2
]
ans[i] = ans[i-1] + 2\times ans[i-2]
ans[i]=ans[i−1]+2×ans[i−2]
第一项显然,第二项乘2是因为可以用两个
2
×
1
2\times 1
2×1横着放或者摆一个
2
×
2
2\times 2
2×2来占满
2
×
2
2 \times 2
2×2大小的空间,因此后面一项系数为2。(不放两个横着放是
2
×
1
2\times 1
2×1是因为会和前面的那种有重复情况)
#include <iostream>
using namespace std;
//HDU Accepted 2501 0MS 1396K 249 B G++
//递推
int ans[32];
int main() {
int n, x;
cin>>n;
ans[0] = 0;
ans[1] = 1;
ans[2] = 3;
for(int i=3; i<=30; i++)
ans[i] = ans[i-1] + ans[i-2]*2;
while(n--) {
cin>>x;
cout<<ans[x]<<endl;
}
return 0;
}
四、HDU 2018 母牛的故事
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2018
这题还需要再理解!
代码:
#include<stdio.h>
//HDU Accepted 2018 0MS 1236K 309 B G++
int main() {
int n;
while(scanf("%d", &n) && n != 0) {
int i, sum = 0;
int a[10000] = {0,1,1,1,1};
for(i=5; i<=n; i++) {
a[i] = a[i-3]+a[i-1];//第i天 增长 的牛
}
if(n<=4)
sum=n;
else {
for(i=1; i<=n; i++)
sum = a[i] + sum;//累加起来
}
printf("%d\n", sum);
}
}