题目大意:
对于每个数字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大。
你的任务很简单,给你两个用斐波拉切数最大化表示的两个数字,输出他们相加后用斐波那契最大化表示的数字。
对于30%的数据 长度 <= 1000
对于100%的数据 长度 <= 1000000
题解:
这题其实特别的神奇…
是需要找规律的,当然对于直接高精度的dalao们,我当然是膜拜辣。。
我们先列出一副符合题目的斐波那契数列(从1,2开始):
序1 2 3 4 5 6
fi 1 2 3 5 8 13
A 0 1 0 1
B 0 1 0 0 1
C 0 2 0 1 1
我们考虑C=A+B的情况
此时的C如果化简,我们发现任意一个ai必定为0或1!这个在草稿纸上随便推一下应该都知道的..
对于C上某一位:
①>=1,则我们可以发现,
因为一个直观的斐波那契数列公式是
fi=fi-1+fi-2]
则当f[i]>=1且f[i-1]>=1时我们直接将能使用的对数k递归到f[i+1]去重复进行①②操作
可知k=min{fi,fi-1}
②>=2,则我们推演一下:
F[i-1]+F[i]=F[i+1]
F[i-1]+F[i-2]+F[i]=F[i+1]+F[i-2]
2F[i]=F[i+1]+F[i-2]
那我们可以得出,每2个fi就可以【分解成】1个f[i-2]和一个f[i+1],此时我们能分多少对就分多少对过去然后递归过去,然后重复进行①②操作
代码:
var
ans,a,b:array [-100..1000100] of longint;
i,j,k,n,m,z:longint;
procedure dfs(dep,x:longint);
var
k:longint;
begin
ans[dep]:=ans[dep]+x;
if ans[dep-1]>=1 then
if ans[dep]>=1 then
begin
if ans[dep-1]>ans[dep]
then k:=ans[dep]
else k:=ans[dep-1];
ans[dep]:=ans[dep]-k;
ans[dep-1]:=ans[dep-1]-k;
dfs(dep+1,k);
end;
if ans[dep]>=2 then
begin
k:=ans[dep] div 2;
ans[dep]:=ans[dep] mod 2;
if dep<=2
then dfs(dep-1,k)
else dfs(dep-2,k);
dfs(dep+1,k);
end;
end;
begin
read(n);
for i:=1 to n do read(a[i]);
readln;
read(m);
for j:=1 to m do read(b[j]);
if n>m then z:=n
else z:=m;
z:=z+50;
for i:=1 to z do
ans[i]:=a[i]+b[i];
for i:=1 to z do
begin
if ans[i-1]>=1 then
if ans[i]>=1 then
begin
if ans[i-1]>ans[i]
then k:=ans[i]
else k:=ans[i-1];
ans[i]:=ans[i]-k;
ans[i-1]:=ans[i-1]-k;
dfs(i+1,k);
end;
if ans[i]>=2 then
begin
k:=ans[i] div 2;
ans[i]:=ans[i] mod 2;
if i<=2
then dfs(i-1,k)
else dfs(i-2,k);
dfs(i+1,k);
end;
end;
while ans[z]=0 do dec(z);
write(z,' ');
for i:=1 to z do write(ans[i],' ');
end.