题意:多组输入,每组输入两个01串表示的数a,b。要求表示a+b=c。
- a,b之多40位
- Fibonacci进制: 。从低位到高位,权值分别为1,2,3,5,8,13,,,,,,
题解:就是个模拟a+b。这种模拟题要注意,一半很容易出先小错误。
- 特别注意:a,b可能等于"0"。
收获:训练比赛化——做题的时候不用太考虑每一步骤是怎么出来的,AC算完事儿。之后再来总结。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#define int long long
#define read(x) scanf("%lld", &x)
#define print(a, c) printf("%lld%c", a, c)
#define dbg(x) cout << #x << "===" << x << endl;
#define pb push_back
using namespace std;
const int N = 40 + 10;
char a[N], b[N], c[N];
int fib[N];
int lena, lenb, lenc;
void init(int n) {
fib[1] = 1, fib[2] = 2;
for (int i = 3; i <= n; i++) fib[i] = fib[i - 1] + fib[i - 2];
// fib[49]===12586269025
}
//这里无论是s[]还是*s传递的都是实参,数组的实际实际地址,所以调用函数之后如果在函数内改变数组那么函数外数组也是会变的。
//之前一直没注意,可能是因为并没有改变数组,而只是使用了数组的值
void update(int x, char *s) {
int f = 0, len = 0;
for (int i = 45; i >= 1; i--) {
if (!f && fib[i] > x)
continue;
else if (!f)
f = 1, len = i, s[i + 1] = '\0';
if (fib[i] > x)
s[len - i + 1] = '0';
else
s[len - i + 1] = '1', x -= fib[i];
// cout << x << " " << i << " " << s[len - i + 1] << endl;
}
if (len == 0) s[1] = '0', s[2] = '\0'; // x为0的情况
}
void Print() {
lenc = strlen(c + 1);
int len = lenc + 2;
lena = strlen(a + 1), lenb = strlen(b + 1); //注意长度改变
//为什莫要找出bug,而不是过了样例就交,因为这样你才知道错在哪里,样例很可能只是恰好对了
for (int i = 1; i <= len - lena; i++) putchar(' ');
puts(a + 1);
putchar('+');
for (int i = 2; i <= len - lenb; i++) putchar(' ');
puts(b + 1);
putchar(' '), putchar(' ');
for (int i = 3; i <= len; i++) putchar('-');
puts("");
putchar(' '), putchar(' ');
puts(c + 1);
puts("");
}
signed main() {
init(N - 1);
while (cin >> a + 1 >> b + 1) {
//转化为10进制
int A = 0, B = 0;
lena = strlen(a + 1), lenb = strlen(b + 1);
for (int i = 1; i <= lena; i++)
if (a[i] == '1') A += fib[lena - i + 1];
for (int i = 1; i <= lenb; i++)
if (b[i] == '1') B += fib[lenb - i + 1];
int C = A + B; //答案的十进制形式
// a,b,c转化为fib进制形式
update(A, a);
update(B, b);
update(C, c);
Print();
}
return 0;
}
/*
input:::
11101 1101
1 1
output:::
100101
+ 10001
-------
1001000
1
+ 1
--
10
*/