LGP3424题解
很牛逼,同时也很阴间的一道题。。。。。。
考虑这种数相邻两位必有一 \(0\),考虑直接把数组加起来之后,\(2\) 的两边一定都是 \(0\)。
于是我们考虑从高位到低位调整。
如果出现了一个 \(2\) 只能通过 \(2f_n=f_{n+1}+f_{n-2}\) 来调整,所以我们需要一次调整长度为 \(4\) 的段,且第一位为 \(0\)。(如果遇到连续两个 \(0\) 直接跳过就是了)
能够得到这几种情况:
\[011x,020x
\]
你并目前不关心最后一位,它只是个工具,所以不需要知道具体是多少。但是注意到用 \(2\) 退位的时候会得到 \(3\),所以实际上还有:
\[030x,021x,012x
\]
分别退位和进位可以得到:
\[011x\to 100x
\]
\[020x\to 100(x+1)
\]
\[030x\to 110(x+1)
\]
\[021x\to 110x
\]
\[012x\to 101x
\]
后面两种情况只能够通过退位得到,所以退位完毕后是不会出现连续三个以上的 \(1\) 的。
剩下的就可以直接进位了。
#include<cstdio>
#include<cctype>
const int M=1e6+5;
int n,x,y,f[M];
inline int read(){
int n(0);char s;while(!isdigit(s=getchar()));while(n=n*10+(s&15),isdigit(s=getchar()));return n;
}
signed main(){
x=read()+1;for(int v,i=2;i<=x;++i)v=read(),v&&++f[i];if(x>n)n=x;
y=read()+1;for(int v,i=2;i<=y;++i)v=read(),v&&++f[i];if(y>n)n=y;
for(int i=n+1;i>=2;--i)if(!f[i]){
if(f[i-1]&&f[i-2])++f[i],--f[i-1],--f[i-2];if(f[i-1]>=2)++f[i],++f[i-3],f[i-1]-=2;
}
for(int i=n+1;i>=2;--i)if(!f[i]&&f[i-1]&&f[i-2])++f[i],--f[i-1],--f[i-2];if(f[1])f[2]=f[1];n+=2;
for(int i=4;i<=n;++i)if(!f[i]&&f[i-1]&&f[i-2])++f[i],--f[i-1],--f[i-2];while(!f[n])--n;
printf("%d ",n-1);for(int i=2;i<=n;++i)putchar(f[i]^48),putchar(32);
}