题意:
- () \/<>{}[]这种”对“字符,要同时选用,并且算两个不同字符。
必须中心对称,不然反转后不是一个对称串
- 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);
}
}