D 题
题意 : 所有的序列中所有的颜色最初是白色的,你每次可以使得两个相邻格子染成(RB)或者染成(BR),给你一个已经染好的序列s,问你是否可以从最初所有都是白色序列染成序列s
思路 : 只要染色了,那么必定有R和B,如果只有R没有B,或者只有B没有R就一定是错的,只要有R,并且有B,那就一定可以推出所有的序列,W就相当于 隔板 的作用,考虑一段只用考虑B和R,如果遇到了W就全部重新考虑
#include <bits/stdc++.h>
using namespace std;
void solve()
{
int n;string s;cin >> n >> s;
bool r = false,b = false,f = false;
for(int i = 0;i < n;i ++ )
{
if(s[i] == 'W')
{
if(r ^ b) f = true;
r = false;
b = false;
continue;
}
else
{
if(s[i] == 'B') b = true;
if(s[i] == 'R') r = true;
}
}
if(r ^ b) cout << "NO" << '\n';
else if(f) cout << "NO" << '\n';
else cout << "YES" << '\n';
}
int main()
{
int t;cin >> t;
while(t -- ) solve();
return 0;
}
E
题目大意: 给你n个只有两个字符组成的字符串,满足 (两个不相同的字符串只有一个共同的字符) ,
一共有多少对?
思路 因为只有两个字符,所以我们可以把字符当成数字来处理,那问题就转化成,询问两个数位只有一位共同的数位 的个数,因为是a 到 k 只有11个字符,所以可以将字符转化成 >= 11 进制的数字,这里是转化成26进制
#include <bits/stdc++.h>
#define int long long
using namespace std;
int c[1000];
void solve()
{
memset(c,0,sizeof c);
int n;cin >> n;
for(int i = 1;i <= n;i ++ )
{
string s; cin >> s;
c[(s[0] - 'a') * 26 + (s[1] - 'a')]++;
}
int ans = 0;
for(int i = 0;i <= 26 * 26;i ++ )
{
for(int j = i;j <= 26 * 26;j ++ )
{
int x1 = i / 26,y1 = i % 26;
int x2 = j / 26,y2 = j % 26;
if((x1 == x2) + (y1 == y2) == 1)
{
ans = ans + 1ll * (c[i] * c[j]);
}
}
}
cout << ans << '\n';
}
signed main()
{
int t;cin >> t;
while(t -- ) solve();
}
F
题目大意: 有两个人 A,B,给你n组蛋糕,第i组的蛋糕数量是a[i],A只能从左到右吃蛋糕,B只能从右到左吃蛋糕,不能跳过某组蛋糕,求A,B吃一样的蛋糕数量下,两个人最多能吃多少组蛋糕
思路 双指针,l,r分别从左到右,从右到左,来移动 . l 相当于A,r 相当于B,固定A吃的数量,然后让B从右到左吃蛋糕,当B吃到的蛋糕和A相等时,记录一下他们此时吃了几组蛋糕.
#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(false)
#define cint cin.tie(0)
#define int long long
using namespace std;
const int N = 2e5 + 300,mod = 998244353;
int a[N],s1[N],s2[N];
void solve()
{
int n;cin >> n;
for(int i = 1;i <= n;i ++ )cin >> a[i];
int l = 1,r = n;
int sumA = 0;
int sumB = 0;
int id = 0;
int cnt = 0;
while(l <= r)
{
sumA += a[l];
cnt++;
while(sumB < sumA && l < r)
{
sumB += a[r];
--r;
cnt++;
}
if(sumB == sumA)id = cnt;
++l;
}
cout << id << '\n';
}
signed main()
{
ios;cint;
int t; cin >> t;
while( t -- ) solve();
return 0;
}
G 模拟
这道题就是模拟一下就好了
#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(false)
#define cint cin.tie(0)
#define int long long
using namespace std;
const int N = 210,mod = 998244353;
char a[N][N],b[N][N];
void solve()
{
int n,m;cin >> n >> m;
for(int i = 1;i <= n;i ++ )
for(int j = 1;j <= m;j ++ )
cin >> a[i][j];
for(int i = 1;i <= n;i ++ )
for(int j = 1;j <= m;j ++ )
b[i][j] = '.';
for(int i = 1;i <= m;i ++ )
{
int cnt = 0;
for(int j = 1;j <= n;j ++ ) // 看看这一列有多少个石头
{
if(a[j][i] == '*')
cnt++;
else if(a[j][i] == 'o')
{
b[j][i] = 'o';
for(int k = j - 1;k >= j - cnt;k -- ) // 全部变成石头
{
b[k][i] = '*';
}
cnt = 0;
}
}
if(cnt != 0) // 全部落在最下面
{
for(int k = n;k >= n - cnt + 1;k -- ) // 全部变成石头
{
b[k][i] = '*';
}
}
}
for(int i = 1;i <= n;i ++ )
{
for(int j = 1;j <= m;j ++ )
cout << b[i][j];
cout << '\n';
}
}
signed main()
{
ios;cint;
int t; cin >> t;
while( t -- ) solve();
return 0;
}
H
题目大意: 你可以进行最多k次的 或 操作,使得a[i] = a[i] % pow(2,j) ,j 的范围是 (0,30) ,然后让所有的a[i] 与 操作完成以后的数值最大
思路: 二进制下的 与 操作要使得值最大,最好使得所有的a[i]在二进制下的第i位,全部为1,因为 与 操作下第i位只要有0 与 完一定是 0,所以我们要从高位到低位(优先修改能够使得数值最大位数)使得所有的数字在第i位下尽量全部为1, 使得的数字在第i位下为1的操作就是 或 操作
#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(false)
#define cint cin.tie(0)
#define int long long
using namespace std;
const int N = 2e5 + 100,mod = 998244353;
int a[N],sum[N];
void solve()
{
int n,k;cin >> n >> k;
memset(sum,0,sizeof sum);
for(int i = 1;i <= n;i ++ ) cin >> a[i];
for(int i = 1;i <= n;i ++ )
{
for(int j = 30;j >= 0;j -- )
if(a[i] >> j & 1)
sum[j]++;
}
// for(int i = 30;i >= 1;i -- ) s += (1 << i);
// cout << s << '\n';
//
int ans = 0;
for(int i = 30;i >= 0;i -- )
{
if(sum[i] == n)
ans += (1 << i);
else
{
if(k >= (n - sum[i]) && k > 0)
{
k = k - (n - sum[i]);
ans += (1 << i);
}
}
}
cout << ans << '\n';
}
signed main()
{
ios;cint;
int t; cin >> t;
while( t -- ) solve();
return 0;
}