【JZOJ 3769】【NOI2015模拟8.14】A+B

问题描述
对于每个数字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]);
}

猜你喜欢

转载自blog.csdn.net/fallen_angel001/article/details/79284408