P7814 「小窝 R3」心の記憶

提供一个最劣解

你们几十毫秒跑完的东西,我要几百毫秒。

显然,以下几种情况是无解的:

  • n=mn=m

  • n=1n=1

  • A=A=01

  • A=A=10

特判一下就好了。

注:下文提到的相反数字指的是:00 的相反数字是 1111 的相反数字是 00

为了保证子序列相同,我们先令答案 BBAA

可是这样 BB 的前缀和 AA 就相等了,于是我们把 BB 的最后一个字符变成相反的数字

然后在末尾插入剩下 mnm-n 个字符。

插入第 ii 个字符 (0i<mn)(0\le i<m-n) 时我们采取如下贪心策略:

  • 如果 A0n2=Bi+1n+i1A_{0\sim n-2}=B_{i+1\sim n+i-1},则加入 An1A_{n-1} 的相反数字。

  • 否则,加入 An1A_{n-1}

也就是说,如果加入 An1A_{n-1} 不符合要求,就加入它的相反数字。

然而这样过不了以下两种情况:

  • 000000……1

  • 111111……0

怎么办呢?其实加入操作在前面和在后面是一样的,我们把这个 AA 翻转,打上标记,按前面的求一遍,对照标记反着输出就可以了。

#include<bits/stdc++.h>
using namespace std;
int read()
{
	int x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
void write(int x)
{
    if(x<0)
        putchar('-'),x=-x;
    if(x>9)
        write(x/10);
    putchar(x%10+'0');
}
int t,n,m;
string s,s1,s2;
bool fl;
char f(char c){//求c的相反数字 
	if(c=='0')
		return '1';
	else
		return '0';
}
int q0(){//0的个数 
	int ans=0;
	for(int i=0;i<s.size();i++)
		if(s[i]=='0')
			ans++;
	return ans;
}
int main()
{
    t=read();
    while(t--){
    	n=read();
    	m=read();
    	cin>>s;
    	if(n==m||n==1||s=="01"||s=="10"){//无解特判 
    		puts("-1");
    		continue;
		}
		fl=0;
		if((q0()==1&&s[n-1]=='0')||(q0()==n-1&&s[n-1]=='1'))
		{
			for(int i=0;i<n/2;i++)
				swap(s[i],s[n-1-i]);
			fl=1;//打上标记 
		}
		s1=s2=s.substr(0,n-1);
		for(int i=0;i<=m-n;i++){
			if(s1.substr(i,n-1)==s2)
				s1+=f(s[n-1]);
			else
				s1+=s[n-1];
		}
		if(fl){
			for(int i=s1.size()-1;i>=0;i--)
				putchar(s1[i]);
		}
		else
			for(int i=0;i<s1.size();i++)
				putchar(s1[i]);
		putchar('\n');
	}
	return 0;
}
posted @ 2021-08-18 00:33  luckydrawbox  阅读(9)  评论(0)    收藏  举报  来源