51Nod-1946-特殊表示法
阿新 • • 發佈:2019-01-04
描述
題解
首先我們來分析一下斐波那契數列的基本性質,眾所周知,斐波那契數列從第二項開始後,能夠組合(每一項只有選與不選兩種操作)出來任意自然數,所以才會有這個特殊表示法的存在,並且這個表示法裡不存在任意兩個連著的
至此,我們來考慮兩個序列疊加在一起後可能存在的情況。首先
但是此時提交還會有
可以加上輸入輸出外掛優化一下,我比較懶,只是將輸出部分先存在字串然後統一輸出了一下,節約了一些時間,輸入的時候也可以整行讀入然後處理一下,比較容易,但是架不住我懶。
程式碼
#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 1e6 + 5;
int n, m;
int a[MAXN];
int b[MAXN];
char c[MAXN << 1];
int main()
{
scanf("%d", &n);
getchar();
for (int i = 0; i < n; i++)
{
a[i] = getchar() - '0';
getchar();
}
scanf ("%d", &m);
getchar();
for (int i = 0; i < m; i++)
{
a[i] += getchar() - '0';
getchar();
}
// 逆著擴充套件一遍
n = max(m, n);
for (int i = n - 1; i > 1; i--)
{
if (a[i] >= 2)
{
// ex: 2 * 5 = 8 + 2
a[i] -= 2;
a[i - 2] += 1;
a[i + 1] += 1;
n = max(i + 2, n);
}
if (a[i] >= 1 && a[i - 1] >= 1)
{
// ex: 2 + 3 = 5
a[i] -= 1;
a[i - 1] -= 1;
a[i + 1] += 1;
n = max(i + 2, n);
}
}
// 處理邊界特殊情況
if (a[0] >= 2 && a[1] == 0)
{
// ex: 1 + 1 = 2
a[0] -= 2;
a[1] += 1;
}
else if (a[1] == 3)
{
// ex: 2 + 2 + 2 = 1 + 2 + 3
a[1] -= 1;
a[0] += 1;
a[2] += 1;
}
// 正著擴充套件若干遍,一直到無法擴充套件
int flag = 1;
while (flag)
{
flag = 0;
for (int i = 0; i < n; i++)
{
if (a[i] >= 1 && a[i + 1] >= 1 && a[i + 2] != 1)
{
flag = 1;
// ex: 2 + 3 = 5
a[i] -= 1;
a[i + 1] -= 1;
a[i + 2] += 1;
n = max(i + 3, n);
}
}
}
int cnt = 0;
for (int i = 0; i < n; i++)
{
c[cnt++] = a[i] + '0';
if (i != n - 1)
{
c[cnt++] = ' ';
}
}
c[cnt] = '\n';
printf("%d\n%s", n, c);
return 0;
}