Description
对于每个数字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大。
你的任务很简单,给你两个用斐波拉切数最大化表示的两个数字,输出他们相加后用斐波那契最大化表示的数字。
Input
两行,分别表示两个数字
每一行开头一个n,表示长度
然后紧接着n个数字,为从低位到高位。
Output
同输入格式。一行。
Sample Input
4 0 1 0 1 5 0 1 0 0 1
Sample Output
6 1 0 1 0 0 1
Data Constraint
对于30%的数据 长度 <= 1000
对于100%的数据 长度 <= 1000000
算出十进制值相加后再用斐波那契最大化表示显然接受不了,我们得在序列里找出规律。
这里有两个不难发现的运算法则:
1.如果有连续两位i,i-1是1,那么它们可以“运算”使得第三位i+1是1. 如 0 1 0 1 1 0 = 0 1 0 0 0 1
2.如果这个位i是2,那么它可以使它的后一位i+1和前两位i-2是1. 如 0 0 2 0 0 1 0=1 0 0 1 0 1 0
随便弄上十几次这样就可以了。
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 int f[10000002],n,x,len1,len2; 5 int main(){ 6 f[0]=0; 7 f[1]=0; 8 f[2]=0; 9 scanf("%d",&len1); 10 for (int i=1;i<=len1;i++) 11 scanf("%d",&f[i]); 12 scanf("%d",&len2); 13 for (int i=1;i<=len2;i++){ 14 int x=0; 15 scanf("%d",&x); 16 f[i]+=x; 17 } 18 int qwq=max(len1,len2); 19 int qoq=true; 20 do{ 21 qoq=false; 22 int qaq=qwq; 23 for (int i=2;i<=qwq;i++){ 24 if ((f[i-1])&&(f[i])){ 25 f[i+1]++; 26 qwq=max(qwq,i+1); 27 f[i]--; 28 f[i-1]--; 29 } 30 } 31 if (f[1]==2){ 32 f[2]++; 33 f[1]=0; 34 } 35 if (f[2]==2){ 36 f[3]++; 37 qwq=max(qwq,3); 38 f[1]++; 39 f[2]=0; 40 } 41 bool quq=true; 42 do{ 43 quq=false; 44 for (int i=3;i<=qaq;i++){ 45 if (f[i]>=2){ 46 quq=true; 47 f[i+1]++; 48 qwq=max(i+1,qwq); 49 f[i-2]++; 50 f[i]--; 51 f[i]--; 52 } 53 } 54 if (quq) qoq=true; 55 } while(quq); 56 } while(qoq); //直到没修改为止 57 printf("%d ",qwq); 58 for(int i=1;i<=qwq;i++) 59 printf("%d ",f[i]); 60 return 0; 61 }
神奇的代码
时间: 2024-10-16 00:57:05