传送门:POJ 2116 - Death to Binary?

题目大意:

有两个数,这两个数以斐波那契基数的形式给出。对应的斐波那契序列以 $Fib[0]=1, Fib[1]=2$ 开始。比如题目描述中的例子,数字 $40$,用斐波那契基数表示,可以是 $1101001$,也可以是 $10001001$,这里以第一个为例来解释,类似二进制,只不过右数第 $k$ 位($k$从 $0$ 开始)对应的不再是 $2^k$,而是 $Fib[k]$,因为 $40=Fib[6]+Fib[5]+Fib[3]+Fib[0]$,和二进制一样,某一位上有值的为 $1$,没有的为 $0$,所以 $40=1101001_{Fib}$。然后告诉你,每个数字用斐波那契基数表示时,有唯一的一种表示是不包含两个连续 $1$ 的,让你拿这种情况去计算。给你两个斐波那契基数表示的数(不一定是没有连续 $1$ 的形式),让你计算加法,最后也以斐波那契基数的表示形式输出结果。然后对输出的格式有一定的要求,并且输出的数还得是那种没有连续 $1$ 形式(我有一句MMP不知当讲不当讲)。

解题思路:

讲道理这个题很简单,但是做起来很坑很坑。WA了好多发。这里说一下那些坑,大家就肯定会做了。
坑1:输入可能包含前导 $0$。
坑2:输入可能是 $0\ 0$ 这种。
坑3:如果从高位往后依次进位 $11$ 为 $100$ 的话,可能导致高位重新出现 $11$, 比如 $1011$,进位后是 $1100$,这里我的做法是每轮扫描都从头开始,反正才 $40$ 的长度。
坑4:格式化输出废了我好多行代码,差评!
另外注意下初始化,然后如果用数组的稍微开大一点,两个 $40$ 位的相加最长会有 $43$ 位,不过我是用字符串做的,所以无所谓了。

通过代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <iostream>
#include <string>
using namespace std;
string x, y;
int fib[45] = {1, 2};
void delete0(string &s)
{
int i = 0;
while (i < s.size() - 1 && s[i] == '0')
++i;
s = s.substr(i);
}
void rep(string &s)
{
int pos = s.find("11", 0);
while (pos != string::npos)
{
if (pos - 1 >= 0 && s[pos - 1] == '0')
s.replace(pos - 1, 3, "100");
else
s.replace(pos, 2, "100");
pos = s.find("11", 0);
}
}
string add(string x, string y)
{
string res = "0";
int b1 = 0, b2 = 0, sum;
int len = x.size();
for (int i = len - 1; i >= 0; --i)
{
b1 += x[i] == '1' ? fib[len - 1 - i] : 0;
b2 += y[i] == '1' ? fib[len - 1 - i] : 0;
}
sum = b1 + b2;
for (int i = 44; i >= 0; --i)
{
if (sum >= fib[i])
{
sum -= fib[i];
res += '1';
}
else
res += '0';
}
delete0(res);
rep(res);
return res;
}
void toequal(string &x, string &y)
{
while (x.size() != y.size())
if (x.size() > y.size())
y = ' ' + y;
else
x = ' ' + x;
}
int main(void)
{
for (int i = 2; i < 45; ++i)
fib[i] = fib[i - 1] + fib[i - 2];
while (cin >> x >> y)
{
delete0(x);
delete0(y);
rep(x);
rep(y);
toequal(x, y);
string res = add(x, y);
toequal(x, res);
toequal(y, res);
string line;
while (line.size() < res.size())
line += '-';
x = " " + x;
y = "+ " + y;
line = " " + line;
res = " " + res;
cout << x << endl
<< y << endl
<< line << endl
<< res << endl
<< endl;
}
return 0
}