题目大意
对于每个数字x,我们总可以把它表示成一些斐波拉切数字之和。我们可以写成
x
=
a
1
∗
F
i
b
1
+
a
2
∗
F
i
b
2
+
a
3
∗
F
i
b
3
+
…
+
a
n
∗
F
i
b
n
x = a1 * Fib1 + a2 * Fib2 + a3 * Fib3 + … + an * Fibn
x=a1∗Fib1+a2∗Fib2+a3∗Fib3+…+an∗Fibn, 其中
F
i
b
1
=
1
,
F
i
b
2
=
2
…
.
F
i
b
[
i
]
=
F
i
b
[
i
–
1
]
+
F
i
b
[
I
−
2
]
Fib1 = 1, Fib2 = 2…. Fib[i] = Fib[i – 1] + Fib[I - 2]
Fib1=1,Fib2=2….Fib[i]=Fib[i–1]+Fib[I−2], 且
a
[
n
]
>
0
a[n] > 0
a[n]>0.那么我们称ai为x的一种斐波拉切表示,我们要求最大化
a
[
1
…
n
]
a[1…n]
a[1…n],如果
b
[
1
…
n
]
b[1…n]
b[1…n]和
a
[
1
…
m
]
a[1…m]
a[1…m]都可以表示
x
x
x,若
m
>
n
m > n
m>n 则
a
a
a更大,若
m
=
n
m = n
m=n,则从高位到低位比,第一个不同处
i
i
i,若
a
i
>
b
i
ai > bi
ai>bi则
a
a
a比
b
b
b大。
你的任务很简单,给你两个用斐波拉切数最大化表示的两个数字,输出他们相加后用斐波那契最大化表示的数字。
n
<
=
1000000
n <= 1000000
n<=1000000
分析
对于这道题很显然你不能将其转化为十进制数再转回去这样肯定时间复杂度过不去。那么分析该如何处理这道题,首先有两个很浅显的性质。
- 若 a [ i ] a[i] a[i]和 a [ i + 1 ] a[i + 1] a[i+1]都有值,那么可以将其和转为 a [ i + 2 ] a[i +2] a[i+2]
- 若 a [ i ] = = 2 a[i] == 2 a[i]==2那么可以将其转化为 a [ i − 2 ] a[i - 2] a[i−2]与 a [ i + 1 ] a[i + 1] a[i+1]
有了以上这两个性质就可以比较流畅地处理出这道题了,直接暴力在外面套一个 w h i l e while while循环,不断用上面两个性质都序列进行更新,当无法再更新时就输出答案,正确性不知道咋整,时间复杂度也是玄学的。还要注意处理一下边界值。
#include <cstdio>
using namespace std;
const int N = 1e6 + 10;
int n,m,a[N],ans[N];
bool flag = 1;
int read()
{
int x = 0;
char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
return x;
}
int min(int a,int b) {return a < b ? a : b;}
int main()
{
n = read();
for (int i = 1; i <= n; ++ i) a[i] = read();
m = read();
for (int i = 1,u; i <= m; ++ i) u = read(),a[i] += u;
n = n > m ? n : m;
while (flag)
{
flag = 0;
for (int i = 2,k; i <= n; ++ i)
if (a[i] && a[i - 1]) k = min(a[i],a[i - 1]),a[i + 1] += k,a[i] -= k,a[i - 1] -= k,flag = 1;
if (a[n + 1]) ++ n;
for (int i = 2; i <= n; ++ i)
if (a[i] >= 2) ++ a[i + 1],++ a[i - 2],---- a[i],flag = 1;
if (a[n + 1]) ++ n;
a[1] += a[0],a[0] = 0;
if (a[1] >= 2) a[2] += a[1] / 2,a[1] = a[1] & 1 ? 1 : 0,flag = 1;
}
printf("%d ",n);
for (int i = 1; i <= n; i ++) printf("%d ",a[i]);
return 0;
}