问题描述
对于每个数字x,我们总可以把它表示成一些斐波拉切数字之和,比如8 = 5 + 3, 而22 = 21 + 1,因此我们可以写成 x = a1 * Fib1 + a2 * Fib2 + a3 * Fib3 + … + an * Fibn, 其中,Fib1 = 1, Fib2 = 2…. Fib[i] = Fib[i – 1] + Fib[I - 2], 且a[n] > 0.那么我们称ai为x的一种斐波拉切表示,由于表示方法有很多种,我们要求最大化a[1…n],即,如果b[1…n]和a[1…m]都可以表示x,若m > n 则a更大,若 m = n, 则从高位到低位比,第一个不同处i,若ai > bi 则a比b大。
你的任务很简单,给你两个用斐波拉切数最大化表示的两个数字,输出他们相加后用斐波那契最大化表示的数字。
输入
两行,分别表示两个数字
每一行开头一个n,表示长度
然后紧接着n个数字,为从低位到高位。
输出
同输入格式。一行。
样例输入
4 0 1 0 1
5 0 1 0 0 1
样例输出
6 1 0 1 0 0 1
算法讨论
嘛我们找找规律,发现了神奇的进位方式,当相加后第i位大于等于2时,第i位减2,i+1位加1,当i-2大于0时第i-2位加1,否则当i-1位大于0时第i-1位加1。当第i位和第i+1位都等于1时,第i、i+1位减1,第i+2位加1.
#include <cstdio>
using namespace std;
#define maxn 1000006
int a[maxn],b[maxn],c[maxn];
int n,n1,n2;
int max(int a,int b)
{
return a>b?a:b;
}
bool check()
{
for (int i=1;i<=n;i++)
if (a[i]==a[i+1] && a[i]!=0 || a[i]>=2)
return 0;
return 1;
}
int work()
{
int t=n;
for (int i=t;i>=1;i--)
{
if (a[i]==0)
continue;
if (a[i]>=2)
{
a[i+1]+=1;
if (i==2)
a[i-1]+=1;
else
if (i!=1)
a[i-2]+=1;
a[i]-=2;
if (i+1>n)
n=i+1;
}
if (a[i]==1 && a[i-1]==1)
{
a[i+1]+=1;
a[i]--; a[i-1]--;
if (i+1>n)
n=i+1;
}
}
}
int main()
{
scanf("%d",&n1);
for (int i=1;i<=n1;i++)
scanf("%d",&a[i]);
scanf("%d",&n2);
for (int i=1;i<=n2;i++)
{
scanf("%d",&b[i]);
a[i]+=b[i];
}
n=max(n1,n2);
while (!check())
work();
printf("%d ",n);
for (int i=1;i<=n;i++)
printf("%d ",a[i]);
}