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);
}
posted @ 2022-07-23 09:00  Prean  阅读(20)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};