題目鏈接
這一場打的又很差,我是fw,C想不出來。
A題
題意:給你一個字符串,問你有沒有辦法往里添一個'a',使得它不是一個回文串。
思路:顯然只有整個字符串全是'a'才無解,否則對字符串進行掃描,對稱位置不是'a'的地方放'a'即可。
代碼如下
char s[N];
int main()
{
IOS;
int T;
cin >> T;
while(T --)
{
cin >> s;
int len = strlen(s);
bool flag = false;
for(int i = 0 ; i < len ; i ++)
if(s[i] != 'a') flag = true;
int d;
if(!flag) cout << "NO\n";
else
{
cout << "YES\n";
int d;
for(int i = 0 ; i < len ; i ++)
if(s[len - i - 1] != 'a')
{
d = i;
break;
}
for(int i = 0 ; i < len ; i ++)
{
if(i == d) cout << 'a';
cout << s[i];
}
cout << "\n";
}
}
return 0;
}
B題
題意:給你一個01初始序列和目標序列,每次可以選擇前 \(2*x\)個位置異或1(前提是選擇區域的0和1個數相等),問你有沒有辦法變成目標序列。
思路:直接找到最長的需要變換的地方,l[i],r[i]分別表示0~i中0和1的個數,每操作一次,都應該使得要操作的區間長度減小,模擬這個過程即可。
代碼如下
char s[N];
char mb[N];
int l[N], r[N];
int main()
{
IOS;
int T;
cin >> T;
while(T --)
{
int n;
cin >> n;
cin >> s;
cin >> mb;
if(s[0] == '0') l[0] ++;
else r[0] ++;
for(int i = 1 ; i < n ; i ++)
{
l[i] = l[i - 1];
r[i] = r[i - 1];
if(s[i] == '0') l[i] ++;
else r[i] ++;
}
int len = -1;
for(int i = 0 ; i < n ; i ++)
if(s[i] != mb[i]) len = i;
bool flag = true;
int time = 1;
while(len >= 0)
{
int pre = len;
if(l[len] != r[len])
{
flag = false;
break;
}
if(time & 1)
for( ; len >= 0 && s[len] != mb[len] ; len --);
else
for( ; len >= 0 && s[len] == mb[len] ; len --);
time ++;
}
if(flag) cout << "YES\n";
else cout << "NO\n";
for(int i = 0 ; i < n ; i ++) l[i] = r[i] = 0;
}
return 0;
}
C題
題意:給你一個01序列,問你能不能構造兩個合法的括號序列a,b,使得當\(s[i] = 1時,a[i] = b[i], 當s[i] = 0時,a[i] \neq b[i]\)。
思路:首先,兩個括號序列的開頭一定是'(',結尾一定是')',其次,由於兩個左右括號之和都是n,而n是偶數,因此01序列中0的個數必須是偶數。必須滿足上述條件才有解,然后構造序列的方式為,先雙指針掃描左右兩端的'1',左邊放左括號,右邊放右括號,然后從頭開始掃描0,輪流放左右括號,另一個序列反之即可。
代碼如下
int n;
char s[N];
char ans[N];
int main()
{
IOS;
int T;
cin >> T;
while(T --)
{
cin >> n;
cin >> s + 1;
bool flag = true;
int cnt = 0;
if(s[1] != '1' || s[n] != '1') flag = false;
for(int i = 2 ; i < n ; i ++)
if(s[i] == '0') cnt ++;
if(cnt & 1) flag = false;
if(!flag) cout << "NO\n";
else
{
cout << "YES\n";
int l = 1, r = n;
while(l < r)
{
while(s[l] != '1') l ++;
while(s[r] != '1') r --;
if(l >= r) break;
ans[l ++] = '(', ans[r --] = ')';
}
int cnt = 0;
for(int i = 1 ; i <= n ; i ++)
if(s[i] == '0')
{
cnt ++;
if(cnt & 1) ans[i] = '(';
else ans[i] = ')';
}
for(int i = 1 ; i <= n ; i ++) cout << ans[i];
cout << "\n";
cnt = 0;
for(int i = 1 ; i <= n ; i ++)
if(s[i] == '0')
{
cnt ++;
if(cnt & 1) ans[i] = ')';
else ans[i] = '(';
}
for(int i = 1 ; i <= n ; i ++) cout << ans[i];
cout << "\n";
}
}
return 0;
}
D題
題意:在一個n∗n的網格中做游戲,使用3種顏色對每個網格塗色
每回合系統會給出一種禁止的顏色a
你必須選擇一個網格,使用除a以外的兩種顏色任意一種對其進行塗色
需要保證沒有相鄰的網格顏色是相同的
做完這n∗n回合游戲以獲得勝利
思路:首先把這\(n * n\)個位置分成奇數位置和偶數位置(所有的奇數位置和偶數位置一定是不相鄰的,奇數位置和奇數位置也不相鄰,偶數位置同理),然后事實上,我們只需要用兩種顏色分別填充奇數位和偶數位,就可填滿整個網格。因此我們默認一種顏色填充奇數位,另一種顏色填充偶數位,因為有三種顏色,因此我們總可以在這兩種默認顏色中選一種,直到出現了某種位置的數放滿了,此時我們只要把剩下的一個非默認顏色混進一種位置即可。
代碼如下
int n, x, c;
int odd = 1, even = 2;
vector<pii> od, ev;
int main()
{
IOS;
cin >> n;
for(int i = 1 ; i <= n ; i ++)
for(int j = 1 ; j <= n ; j ++)
{
if((i + j) & 1) od.push_back({i, j});
else ev.push_back({i, j});
}
int l = 0, r = 0;
for(int i = 0 ; i < n * n ; i ++)
{
cin >> x;
if(x != odd && l < od.size()) //如果可以在od上放odd
{
cout << odd << " " << od[l].x << " " << od[l].y << endl;
cout.flush();
l ++;
}
else if(x != even && r < ev.size()) //可以在ev上放even
{
cout << even << " " << ev[r].x << " " << ev[r].y << endl;
cout.flush();
r ++;
}
else
{
if(l < od.size())
{
cout << 3 << " " << od[l].x << " " << od[l].y << endl;
cout.flush();
l ++;
}
else
{
cout << 3 << " " << ev[r].x << " " << ev[r].y << endl;
cout.flush();
r ++;
}
}
}
return 0;
}