Algorithm19 递推与递归
[TOC]
递推与递归
斐波那契数列 (高精度)
https://www.luogu.com.cn/problem/P1255
(相似题目:https://www.luogu.com.cn/problem/P2437)
题目大意:上楼梯,一次上一步或者一次上两步,问上n阶的楼梯可以有多少种走法
1、递推公式:d[i] = d[i-1]+d[i-2];
2、斐波那契数列在n=50的时候就已经将int爆掉,所以如果n=5000的时候需要用高精度。
AC代码:
#include <iostream>
using namespace std;
#define maxn 5005
typedef long long ll;
#include <cstring>
const int N = 2005;
struct BigInt {
int len, s[N];
BigInt() {memset(s, 0, sizeof(s));len = 1;}
BigInt(int num) { *this = num; }
BigInt(char *num) { *this = num; }
BigInt operator=(int num) {
char c[N];
sprintf(c, "%d", num);
*this = c;
return *this;
}
BigInt operator=(const char *num) {
len = strlen(num);
for (int i = 0; i < len; i++) s[i] = num[len - 1 - i] - '0';
return *this;
}
string str() {
string res = "";
for (int i = 0; i < len; i++) res = (char) (s[i] + '0') + res;
return res;
}
void clean() {while (len > 1 && !s[len - 1]) len--;}
BigInt operator + (const BigInt &b) {
BigInt c;
c.len = 0;
for (int i = 0, g = 0; g || i < len || i < b.len; i++) {
int x = g;
if (i < len) x += s[i];
if (i < b.len) x += b.s[i];
c.s[c.len++] = x % 10;
g = x / 10;
}
return c;
}
BigInt operator - (const BigInt &b) {
BigInt c;
c.len = 0;
int x;
for (int i = 0, g = 0; i < len; i++) {
x = s[i] - g;
if (i < b.len) x -= b.s[i];
if (x >= 0) g = 0;
else {
x += 10;
g = 1;
};
c.s[c.len++] = x;
}
c.clean();
return c;
}
BigInt operator * (const BigInt &b) {
BigInt c;
c.len = len + b.len;
for (int i = 0; i < len; i++) for (int j = 0; j < b.len; j++) c.s[i + j] += s[i] * b.s[j];
for (int i = 0; i < c.len - 1; i++) {
c.s[i + 1] += c.s[i] / 10;
c.s[i] %= 10;
}
c.clean();
return c;
}
bool operator < (const BigInt &b) {
if (len != b.len) return len < b.len;
for (int i = len - 1; i >= 0; i--)
if (s[i] != b.s[i]) return s[i] < b.s[i];
return false;
}
BigInt operator += (const BigInt &b) {
*this = *this + b;
return *this;
}
BigInt operator -= (const BigInt &b) {
*this = *this - b;
return *this;
}
};
istream &operator>>(istream &in, BigInt &x) {
string s;
in >> s;
x = s.c_str();
return in;
}
ostream &operator<<(ostream &out, BigInt &x) {
out << x.str();
return out;
}
int n;
BigInt d[maxn];
int main() {
scanf("%d", &n);
d[1] = 1, d[2] = 2;
for (int i = 3; i <= n; ++i) d[i] = d[i - 1] + d[i - 2];
cout << d[n] << endl;
return 0;
}
分形-谢尔宾斯基三角
特点:数据规模是二倍的上升;大规模可以缩减成小规模去算去模拟;
https://www.luogu.com.cn/problem/P1498
#include <iostream>
using namespace std;
#define maxl 1030
int n, a[maxl][maxl];
#include <cstring>
#define cl(a, b) memset(a, b, sizeof(a))
#include <cmath>
void draw(int x, int y, int h) {
if (h == 2) {
a[x][y] = 1;
return;
}
int nowh = h >> 1;
for (int i = x; i < x + nowh; ++i)
for (int j = y; j < y + nowh; ++j)
a[i][j] = 1;
draw(x, y + nowh, nowh);
draw(x + nowh, y, nowh);
draw(x + nowh, y + nowh, nowh);
}
void print() {
for (int i = 1; i <= n; i++) {
int j = 1;
while (a[i][j]) {printf(" ");j++;}
for (; j <= n; j++) {
if (i & 1) {
if (a[i][j] == 0)printf("/\\");
else printf(" ");
} else {
if (a[i][j] == 0) {
printf("/__\\");
j++;
} else printf(" ");
}
}
printf("\n");
}
}
int main() {
scanf("%d", &n);
n = pow(2, n);
cl(a, 0); // init
draw(1, 1, n); // draw
print(); // print
return 0;
}
分治思想
https://www.luogu.com.cn/problem/P1228
题目大意:用四种形状来覆盖正方形
思路:分成四个大块,然后把没有点的那个模块的剩下三个模块的端点给覆盖上即可。
#include <iostream>
using namespace std;
#define maxl 1030
int k, x, y, a[maxl][maxl];
#include <cmath>
#include <cstring>
#define cl(a, b) memset(a, b, sizeof(a))
void draw(int x, int y, int h) {
if (h >= 2) {
int nowh = h>>1;
for (int i = x; i < x+h; ++i) {
for (int j = y; j < y+h; ++j) {
if (a[i][j]) {
if (i<x+nowh && j<y+nowh) {a[x+nowh][y+nowh] = a[x+nowh-1][y+nowh] = a[x+nowh][y+nowh-1] = 1;printf("%d %d 1\n", x+nowh, y+nowh);}
else if (i>=x+nowh && j<y+nowh) {a[x+nowh][y+nowh] = a[x+nowh-1][y+nowh-1] = a[x+nowh-1][y+nowh] = 2;printf("%d %d 3\n", x+nowh-1, y+nowh);}
else if (i<x+nowh && j>=y+nowh) {a[x+nowh][y+nowh] = a[x+nowh][y+nowh-1] = a[x+nowh-1][y+nowh-1] = 3;printf("%d %d 2\n", x+nowh, y+nowh-1);}
else if (i>=x+nowh && j>=y+nowh) {a[x+nowh-1][y+nowh-1] = a[x+nowh-1][y+nowh] = a[x+nowh][y+nowh-1] = 4;printf("%d %d 4\n", x+nowh-1, y+nowh-1);}
draw(x, y, nowh);draw(x+nowh, y, nowh);draw(x, y+nowh, nowh);draw(x+nowh, y+nowh, nowh);
return;
}
}
}
}
}
int main() {
scanf("%d%d%d", &k, &x, &y); k = pow(2, k);
cl(a, 0); a[x][y] = 5; // init
draw(1, 1, k); // draw
return 0;
}