【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]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章