1561 字
8 分钟
cf edu round 189
NOTE

比赛链接:Educational Codeforces Round 189 (Rated for Div.2)

A - A Number Between Two Others#

关键词:暴力,签到

Code#

// Problem: CF 2225 A
// Contest: Codeforces - Educational Codeforces Round 189 (Rated for Div. 2)
// URL: https://codeforces.com/contest/2225/problem/A
// Time: 2026-05-16 14:36:37
#include <bits/stdc++.h>
using namespace std;
// clang-format off
#define endl '\n'
#define all(x) (x).begin(), (x).end()
#define fastio() ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
// clang-format on
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pdd = pair<double, double>;
using pll = pair<long long, long long>;
using i128 = __int128;
const int dx[] = {-1, 0, 1, 0, -1, 1, 1, -1};
const int dy[] = {0, 1, 0, -1, 1, 1, -1, -1};
const int inf = 0x3f3f3f3f;
const int N = 0;
void solve()
{
ll x, y;
cin >> x >> y;
for (ll i = x; i <= y; i += x)
{
if (i % x == 0 && y % i != 0)
{
cout << "YES" << endl;
return;
}
}
cout << "NO" << endl;
}
int main()
{
fastio();
int T = 1;
cin >> T;
while (T--)
solve();
return 0;
}

B - Alternating String#

关键词:思维

思路#

题目要求最终的字符串交替,也就是任意的两个字符都不能相同。假如存在 si=si+1s_i = s_{i + 1},我们就说这里存在一个冲突。

题目要求选定一个子串,必须将其位置反转,并且可以选择性地将字符反转。

我们发现,进行这样的操作,不会改变子串内部和外部的冲突数量情况,只会改变边界处。

这就意味着一次操作最多可以消除两个冲突。

Code#

// Problem: CF 2225 B
// Contest: Codeforces - Educational Codeforces Round 189 (Rated for Div. 2)
// URL: https://codeforces.com/contest/2225/problem/B
// Time: 2026-05-16 15:15:59
#include <bits/stdc++.h>
using namespace std;
// clang-format off
#define endl '\n'
#define all(x) (x).begin(), (x).end()
#define fastio() ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
// clang-format on
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pdd = pair<double, double>;
using pll = pair<long long, long long>;
using i128 = __int128;
const int dx[] = {-1, 0, 1, 0, -1, 1, 1, -1};
const int dy[] = {0, 1, 0, -1, 1, 1, -1, -1};
const int inf = 0x3f3f3f3f;
const int N = 0;
void solve()
{
string s;
cin >> s;
int res = 0;
for (int i = 1; i < s.size(); i++)
{
if (s[i] == s[i - 1])
res++;
}
// cout << res << endl;
cout << (res <= 2 ? "YES" : "NO") << endl;
}
int main()
{
fastio();
int T = 1;
cin >> T;
while (T--)
solve();
return 0;
}

C - Red-Black Pairs#

关键词:DP

思路#

这是一个多米诺骨牌覆盖模型,具体结论如下:

2×n2 \times n 的网格中,任何一种无缝隙的骨牌铺法,都可以被拆解为以下两种基础单元的堆叠

  1. 竖放(2×12 \times 1 单元):占用 11 列,上下两个格子配成一对。
  2. 横放(2×22 \times 2 单元):占用 22 列,上下两行各用两个 1×21 \times 2 的横向骨牌(因为如果你只放一个横骨牌,剩下的缺口必然填不满,只能上下都横放,凑成一个 2×22 \times 2 的方块)。

dp[i]dp[i] 表示完美处理完前 ii 列所需的最小修改次数。

当我们在第 ii 列时,只面临两种决策:

  • 决策 A:第 ii 列单独竖放

    我们要把第一行的 aia_i 和第二行的 bib_i 强行配成一对。

    • 如果它们颜色本来就相同,代价是 00;如果不同,我们得改掉其中一个,代价是 11
    • 这种情况下的最小总代价是:dp[i-1] + (a[i] != b[i])
  • 决策 B:第 i1i-1 列和第 ii 列横放

    我们要把 ai1a_{i-1}aia_i 配对,同时把 bi1b_{i-1}bib_i 配对。

    • 对于第一行,如果 ai1aia_{i-1} \neq a_i,代价 +1+1
    • 对于第二行,如果 bi1bib_{i-1} \neq b_i,代价 +1+1
    • 这种情况下的最小总代价是:dp[i-2] + (a[i-1] != a[i]) + (b[i-1] != b[i])

两种决策取最小值即可。注意当 i=1i = 1 时会引发数组越界。

Code#

// Problem: CF 2225 C
// Contest: Codeforces - Educational Codeforces Round 189 (Rated for Div. 2)
// URL: https://codeforces.com/contest/2225/problem/C
// Time: 2026-05-16 15:39:42
#include <bits/stdc++.h>
using namespace std;
// clang-format off
#define endl '\n'
#define all(x) (x).begin(), (x).end()
#define fastio() ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
// clang-format on
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pdd = pair<double, double>;
using pll = pair<long long, long long>;
using i128 = __int128;
const int dx[] = {-1, 0, 1, 0, -1, 1, 1, -1};
const int dy[] = {0, 1, 0, -1, 1, 1, -1, -1};
const int inf = 0x3f3f3f3f;
const int N = 0;
void solve()
{
int n;
cin >> n;
string a, b;
cin >> a >> b;
a = " " + a, b = " " + b;
vector<int> dp(n + 1, inf);
dp[0] = 0;
dp[1] = dp[0] + (a[1] != b[1]);
for (int i = 2; i <= n; i++)
dp[i] = min(dp[i - 1] + (a[i] != b[i]), dp[i - 2] + (a[i - 1] != a[i]) + (b[i - 1] != b[i]));
cout << dp[n] << endl;
}
int main()
{
fastio();
int T = 1;
cin >> T;
while (T--)
solve();
return 0;
}

D - Exceptional Segments#

关键词:异或运算

思路#

NOTE

详见笔记本中的数学章节,写了前缀异或和的性质。

根据异或运算的性质,任意一段区间 [l,r][l, r] 的连续异或和可以表示为:

i=lri=P(r)P(l1)\bigoplus_{i=l}^r i = P(r) \oplus P(l-1)

题目要求这段区间的异或和为 00,这就意味着:

P(r)P(l1)=0    P(r)=P(l1)P(r) \oplus P(l-1) = 0 \implies P(r) = P(l-1)

题目等价于让我们在 L[0,x1]L \in [0, x-1]r[x,n]r \in [x, n] 这两个独立的区间内,寻找有多少对 (L,r)(L, r) 能够满足 P(L)=P(r)P(L) = P(r)

显然 P(L)=P(r)P(L) = P(r) 当且仅当它们都取到了常数值,也就是 0011

  1. 目标值同为 00
  • 要让 P(L)=0P(L) = 0,条件是 L3(mod4)L \equiv 3 \pmod 4L=0L = 0
  • 要让 P(r)=0P(r) = 0,条件是 r3(mod4)r \equiv 3 \pmod 4
  1. 目标值同为 11
  • 要让 P(L)=1P(L) = 1,条件是 L1(mod4)L \equiv 1 \pmod 4
  • 要让 P(r)=1P(r) = 1,条件是 r1(mod4)r \equiv 1 \pmod 4

Code#

// Problem: CF 2225 D
// Contest: Codeforces - Educational Codeforces Round 189 (Rated for Div. 2)
// URL: https://codeforces.com/contest/2225/problem/D
// Time: 2026-05-16 17:19:37
#include <bits/stdc++.h>
using namespace std;
// clang-format off
#define endl '\n'
#define all(x) (x).begin(), (x).end()
#define fastio() ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
// clang-format on
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pdd = pair<double, double>;
using pll = pair<long long, long long>;
using i128 = __int128;
const int dx[] = {-1, 0, 1, 0, -1, 1, 1, -1};
const int dy[] = {0, 1, 0, -1, 1, 1, -1, -1};
const int inf = 0x3f3f3f3f;
const int N = 0;
const ll mod = 998244353;
void solve()
{
ll n, x;
cin >> n >> x;
ll l0 = 1 + x / 4;
ll l1 = (x + 2) / 4;
ll r0 = (n + 1) / 4 - x / 4;
ll r1 = (n + 3) / 4 - (x + 2) / 4;
ll res = (l0 % mod) * (r0 % mod) % mod;
res = (res + (l1 % mod) * (r1 % mod) % mod) % mod;
cout << res << endl;
}
int main()
{
fastio();
int T = 1;
cin >> T;
while (T--)
solve();
return 0;
}