官方题解
https://codeforces.com/blog/entry/89319
A
题意:给定一个串,能否通过若干次添加’a’操作使之变成非回文串,能顺带输出结果
解法:当且仅当给定串全为’a’时必为回文串,其他情况则必可通过加’a’操作构造成非回文串
构造方式:分别向头/尾加’a’,两者比存在非回文答案
AC代码
#include <bits/stdc++.h>
using namespace std;
#define IO std::ios::sync_with_stdio(false); cin.tie(0)
#define ll long long
#define ull unsigned long long
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define rep(i, l, r) for (int i = l; i <= r; ++i)
#define per(i, l, r) for (int i = l; i >= r; --i)
#define mset(s, _) memset(s, _, sizeof(s))
#define mcpy(s, _) memcpy(s, _, sizeof(s))
#define pb push_back
#define pii pair <int, int>
#define vi vector<int>
#define vpii vector<pii>
#define mp(a, b) make_pair(a, b)
#define debug system("pause")
#define pll pair <ll, ll>
#define fir first
#define sec second
#define inf 0x3f3f3f3f
#define pline cout << endl << endl
inline int lowbit(int x) {return x & -x;}
const int N = 1e6 + 10, mod = 1e9 + 7;
int t, n;
int main() {
cin >> t;
while(t -- ) {
string str; cin >> str;
int num = str.size();
int numa = 0;
rep(i, 0, num - 1) {
if(str[i] == 'a') numa ++ ;
}
if(numa == num) {
puts("NO"); continue;
}
string t1, t2 = "a";
t1 = str + "a"; string t11(t1); reverse(t11.begin(), t11.end());
t2 = t2 + str; string t22(t2); reverse(t22.begin(), t22.end());
if(t11 != t1) {
cout << "YES" << endl; cout << t1 << endl;
continue;
} else {
puts("YES"); cout << t2 << endl;
}
}
return 0;
}
B
题意:给定01串,每次能自由将0, 1个数相同的前缀进行取反操作,问能够通过有限次操作将当前串变成目标串
解法:通过观察易得对于0,1个数相同且与目标串匹配的前缀,取反操作后定能复原,而对于0,1串个数不同但是与目标串匹配的前缀,取反操作以后定不能复原,对于不能与目标串匹配的前缀,如果0,1个数相等,则必能通过若干操作将这部分前缀变成目标串前缀,故只需动态的分别统计与目标串匹配和不匹配的前缀的0, 1个数是否相等判断结果即可
AC代码
#include <bits/stdc++.h>
using namespace std;
#define IO std::ios::sync_with_stdio(false); cin.tie(0)
#define ll long long
#define ull unsigned long long
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define rep(i, l, r) for (int i = l; i <= r; ++i)
#define per(i, l, r) for (int i = l; i >= r; --i)
#define mset(s, _) memset(s, _, sizeof(s))
#define mcpy(s, _) memcpy(s, _, sizeof(s))
#define pb push_back
#define pii pair <int, int>
#define vi vector<int>
#define vpii vector<pii>
#define mp(a, b) make_pair(a, b)
#define debug system("pause")
#define pll pair <ll, ll>
#define fir first
#define sec second
#define inf 0x3f3f3f3f
#define pline cout << endl << endl
inline int lowbit(int x) {return x & -x;}
const int N = 1e6 + 10, mod = 1e9 + 7;
int t, n;
int main() {
cin >> t;
while(t -- ) {
cin >> n; string a, b; cin >> a >> b;
if(a == b) {
puts("YES"); continue;
}
int p1 = 0, p0 = 0, up1 = 0, up0 = 0;
bool fg = 1, flag = 0;
for(int i = 0; i < n; ) {
if(a[i] == b[i]) {
flag = 1;
if(i - 1 >= 0 && a[i - 1] != b[i - 1]) {
if(p1 != p0 || up1 != up0) {
fg = 0; break;
}
p0 += up0; p1 += up1; up0 = 0; up1 = 0;
}
if(a[i] == '0') p0 ++ ;
else p1 ++ ;
i ++ ;
}
else {
flag = 0;
if(a[i] == '0') up0 ++ ;
else up1 ++ ;
i ++ ;
}
}
if(flag == 0 && (p1 != p0 || up1 != up0)) fg = 0;
if(fg) puts("YES");
else puts("NO");
}
return 0;
}
C(构造)
题意:给定01串s,能否构造出一组合法括号串A, B使得当s[i] == ‘1’时,A[i] == B[i], 当s[i] == ‘0’时,A[i] != B[i]
解法:1.要保证序列的合法,首先要保证第一个字符必定时’(‘,最后一个字符必定时’)’,故s[0] 与 s[n - 1] 必须为‘1’
2.当01串中‘0’的个数为奇数时,必不存在解
因为给定的n为偶数,对于两个串总体而言,'(' 与 ')'的个数分别为n
对于01串中的'1',若‘1’的个数为奇数,因为A,B中若s[i] == 1,则A[i] == B[i], 故'1'对应下标的'('和')'的个数都必为偶数, '1'的个数为偶数更显然
对于01串中的'0',若’0‘的个数为奇数,因为A,B中若s[i] == 0,则A[i] != B[i], 所以’0‘对应下标的'('与')'的个数必为奇数,这将使得两个串的'(' 与 ')'的个数为奇数,不合题意,故排除
对于0的个数非奇数非奇数的情况,我们可以如下构造出答案,统计出1的个数k,将1的前k/2的位置设置为(, 后k/2位置设置为), 对于0下标对应的位置则一次设置为( , )
[注]:此答案可通过分离1, 0的方式证明必定使得A, B都合法
AC代码
#include <bits/stdc++.h>
using namespace std;
#define IO std::ios::sync_with_stdio(false); cin.tie(0)
#define ll long long
#define ull unsigned long long
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define rep(i, l, r) for (int i = l; i <= r; ++i)
#define per(i, l, r) for (int i = l; i >= r; --i)
#define mset(s, _) memset(s, _, sizeof(s))
#define mcpy(s, _) memcpy(s, _, sizeof(s))
#define pb push_back
#define pii pair <int, int>
#define vi vector<int>
#define vpii vector<pii>
#define mp(a, b) make_pair(a, b)
#define debug system("pause")
#define pll pair <ll, ll>
#define fir first
#define sec second
#define inf 0x3f3f3f3f
#define pline cout << endl << endl
inline int lowbit(int x) {return x & -x;}
const int N = 1e6 + 10, mod = 1e9 + 7;
int t, n;
int main() {
cin >> t;
for(int k = 1; k <= t; k ++ ) {
cin >> n;
string str; cin >> str;
if(t == 64) cout << str << endl;
if(str[0] != '1' || str[n - 1] != '1') {
puts("NO"); continue;
}
int num0 = 0, num1 = 0;
rep(i, 0, n - 1) {
if(str[i] == '0') num0 ++ ;
else num1 ++ ;
}
if(num0 % 2) {
puts("NO"); continue;
}
puts("YES");
string a, b;
int s1 = 0, s0 = 0, t = 0;
rep(i, 0, n - 1) {
if(str[i] == '1') s1 ++ ;
else s0 ++ ;
if(str[i] == '1' && s1 <= num1 / 2) {a += '('; }
else if(str[i] == '1' && s1 > num1 / 2) {a += ')'; }
else if(str[i] == '0' && t == 0) {a += '('; t = 1;}
else {a += ')'; t = 0;}
}
rep(i, 0, n - 1) {
if(str[i] == '1') b += a[i];
else {
if(a[i] == '(') b += ')';
else b += '(';
}
}
cout << a << endl << b << endl;
}
return 0;
}