0
点赞
收藏
分享

微信扫一扫

牛客寒假训练营2 I 小沙的构造(构造)

yundejia 2022-01-30 阅读 52
算法

题意

  • () \/<>{}[]这种”对“字符,要同时选用,并且算两个不同字符。

必须中心对称,不然反转后不是一个对称串

  • TMKO等其他字符也要关于中心对称,算一个不同字符

这个是一个对称串

这个不是一个对称串

我们可以发现,就是要构造一种特殊的回文串,根据回文串的规律,应该从两端同时选用,所以就必须根据串的大小是奇数或者偶数进行特殊处理

  • 串的大小是奇数   需要在正中间加上一个单字符(单字符应该是最后一个单字符),进行偶数操作
  • 串的大小是偶数   在两端同时放置一对对字符,和两个单字符

m的大小也要特殊处理

  • m==1 只要输出一个就可以了
  • m!=1  需要输出多个,找多对

所以要处理的情况有

  • n<2*m                                 输出-1
  • n>=2*m,n<=70                    处理m,n奇偶性
  • n>70                                    重复取相同的m,应该注意取余
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int N = 1e4 + 10;
char res[N];
set<char> cs;

char a[N] = "<[{(\\!'*+-.08:=^_WTYUIOAHXVM|\"";
char b[N] = ">]})/!'*+-.08:=^_WTYUIOAHXVM|\"";
int main()
{
	int n, m;
	cin >> n >> m;
	if (m == 1)	//只有一个不同字符
		while (n--) putchar(34);
	else
	{
		if (n & 1)	//奇数,随便放一个
			res[ 1+n >> 1] = 34, cs.insert(34);
		//这里因为“放在最后面,所以输出引号,换成其他的可能在m<35时,最后无法构成串,导致答案错误
		for (int l = 1, r = n, j = n / 2, k = 0;j;l++, r--, j--)
		{//l左端点,r右端点,
			if (cs.size() + 1 == m) //对于m是奇数的情况
				k = max(k, 5);	//只需要再放入一个,0~4表示对字符,5以后表示单字符
			//两端同时放入
			res[l] = a[k], res[r] = b[k];
			cs.insert(a[k]);cs.insert(b[k]);
			if (cs.size() < m)
				k++;
			k %= 30;	//5个对字符,35-5
		}
		puts(cs.size() != m ? "-1" : res+1);
	}
}

举报

相关推荐

0 条评论