Problem A
题面:
特里皮·特罗皮生活在一个奇怪的世界。每个国家的古名都由三串字组成。每个字符串的第一个字母被连接起来,形成这个国家的现代名称。
给定国家的古代名称,请输出现代名称。
题解:
输出三个字符串的首字符即可
AC代码:
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;
using u128 = unsigned __int128;
void solve()
{
string s;
for (int i = 0; i < 3;i++){
cin >> s;
cout << s[0];
}
cout << endl;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
Problem B
题面:
在波布里托-班迪托居住的小镇上,在一条无穷数线上有无数的房子,房子的位置是 … , − 2 , − 1 , 0 , 1 , 2 , … \ldots, -2, -1, 0, 1, 2, \ldots …,−2,−1,0,1,2,… 。在第 0 0 0 天,他让房子 0 0 0 的不幸居民感染了瘟疫。接下来的每一天,瘟疫都会传播到***个健康的家庭,而这些家庭都紧挨着一个受感染的家庭。可以看出,每天受感染的房屋形成一个连续的片段。
假设从 l l l (第3户)开始到 r r r (第3户)结束的这一段被记为 [ l , r ] [l, r] [l,r] 。你知道在 n n n 天后, [ l , r ] [l, r] [l,r] 段受到感染。请找出可能在第 m m m 天( m ≤ n m \le n m≤n )被感染的线段 [ l ′ , r ′ ] [l', r'] [l′,r′] 。
题解:
创建两个边界,在没有到达左边界以及没有到第m天的情况下,向左移动左边界,如还有天数剩余,向右移动右边界
AC代码:
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;
using u128 = unsigned __int128;
void solve()
{
int n, m, l, r;
cin >> n >> m >> l >> r;
int l1 = 0, r1 = 0;
for(int i=0;i<m;i++){
if(l1>l){
l1--;
}else {
r1++;
}
}
cout << l1 << " " << r1 << endl;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
Problem C
题面:
Brr Brr Patapim 正试图知道 Tiramisù 的秘密密码,那是 2 ⋅ n 2\cdot n 2⋅n 个元素的排列组合 ∗ ^{\text{∗}} ∗ 。为了帮助帕塔皮姆猜测,提拉米苏给了他一个 n × n n\times n n×n 网格 G G G ,其中 G i , j G_{i,j} Gi,j (或者说网格中 i i i /th行和 j j j /th列中的元素)包含 p i + j p_{i+j} pi+j ,或者说排列中的 ( i + j ) (i+j) (i+j) /th元素。
给定这个网格,请帮助帕塔皮姆破解被遗忘的密码。可以保证这个排列是存在的,而且可以证明这个排列是唯一确定的。
∗ ^{\text{∗}} ∗ m m m 个整数的排列是 m m m 个整数的序列,其中每个整数都恰好包含 1 , 2 , … , m 1,2,\ldots,m 1,2,…,m 次。例如, [ 1 , 3 , 2 ] [1, 3, 2] [1,3,2] 和 [ 2 , 1 ] [2, 1] [2,1] 是排列,而 [ 1 , 2 , 4 ] [1, 2, 4] [1,2,4] 和 [ 1 , 3 , 2 , 3 ] [1, 3, 2, 3] [1,3,2,3] 不是排列。
题解:
我们观察到对于n阶的行列式,副对角线的元素相同,因此只需要输出网格的第一行和最后一列,并在这之前输出MEX
AC代码:
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;
using u128 = unsigned __int128;
void solve()
{
int n;
cin >> n;
vector<vector<int>> num(n, vector<int>(n));
vector<int> seen(n * 2 + 1, 0);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
int a;
cin >> a;
num[i][j] = a;
seen[a]++;
}
}
for (int i = 1; i <= n * 2; i++)
{
if (seen[i] == 0)
{
cout << i << " ";
break;
}
}
for (int j = 0; j < n; j++)
{
cout << num[0][j] << " ";
}
for (int i = 1; i < n - 1; i++)
{
cout << num[i][n - 1] << " ";
}
if (n != 1)
cout << num[n - 1][n - 1] << endl;
else
cout << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
Problem D
题面:
你面前有两面鼓:一面是左鼓,一面是右鼓。敲击左边的鼓可以记录为 “L”,敲击右边的鼓可以记录为 “R”。
统治这个世界的奇异力量是善变的:有时敲击一次,有时敲击两次。因此,敲击左边鼓的声音可能是 "L "或 “LL”,敲击右边鼓的声音可能是 "R "或 “RR”。
击鼓的顺序记录在字符串 p p p 中,听到的声音记录在字符串 s s s 中。给定 p p p 和 s s s ,判断字符串 s s s 是否可能是字符串 p p p 敲击的结果。
例如,如果 p = p= p= “LR”,那么点击的结果可能是 “LR”、“LRR”、"LLR "和 "LLRR "中的任何一个,但字符串 "LLLR "或 "LRL "则不可能。
题解:
从头遍历两个字符串,记录相同元素个数cntp,cnts,每到第一个不同的元素,就先进行判断。如果
c
n
t
s
<
c
n
t
p
cnts<cntp
cnts<cntp或者
c
n
t
s
>
c
n
t
p
×
2
cnts > cntp\times2
cnts>cntp×2,则不可能,
若满足条件则继续遍历判断,直到一个字符串遍历结束。此时如果其中一个字符串的索引没有完全遍历字符串,则不可能
AC代码:
#include <bits/stdc++.h>
using namespace std;
void solve()
{
string p, s;
cin >> p >> s;
int i = 0, j = 0;
while (i < p.size() && j < s.size())
{
if (p[i] != s[j])
{
cout << "NO\n";
return;
}
int cntp = 0;
char ch = p[i];
while (i < p.size() && p[i] == ch)
{
cntp++;
i++;
}
int cnts = 0;
while (j < s.size() && s[j] == ch)
{
cnts++;
j++;
}
if (cnts < cntp || cnts > cntp * 2)
{
cout << "NO\n";
return;
}
}
if (i == p.size() && j == s.size())
{
cout << "YES\n";
}
else
{
cout << "NO\n";
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
Problem E
题面:
博尼卡-安巴拉布给你一个由 n n n 个整数 a 1 , a 2 , … , a n a_1,a_2,\ldots,a_n a1,a2,…,an 组成的序列。
请输出所有 1 ≤ k ≤ n 1 \leq k \leq n 1≤k≤n 中 ( a k ⊕ a 1 ) + ( a k ⊕ a 2 ) + … + ( a k ⊕ a n ) (a_k\oplus a_1)+(a_k\oplus a_2)+\ldots+(a_k\oplus a_n) (ak⊕a1)+(ak⊕a2)+…+(ak⊕an) 的最大值。注意 ⊕ \oplus ⊕ 表示 bitwise XOR 运算。
题解:
对于每一位,从高到低遍历,记录每一位上 1 的数量。然后对于数组中每个元素 ak,我们逐位判断它是否是 1,如果是:它这一位对异或结果有贡献的是0 的数量。如果它是 0,则贡献的是1 的数量。所以我们可以计算每个ak的异或和
AC代码:
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;
using u128 = unsigned __int128;
void solve()
{
int n;
cin >> n;
vector<int> a(n);
for (auto &x : a)
cin >> x;
const int bit = 30;
vector<int> cnt1(bit, 0);
for (int x : a)
{
for (int b = 0; b < bit; b++)
{
if (x & (1 << b))
cnt1[b]++;
}
}
i64 ans = 0;
for (int i = 0; i < n; ++i)
{
i64 sum = 0;
for (int b = 0; b < bit; ++b)
{
if (a[i] & (1 << b))
{
sum += 1LL * (n - cnt1[b]) * (1 << b);
}
else
{
sum += 1LL * cnt1[b] * (1 << b);
}
}
ans = max(ans, sum);
}
cout << ans << '\n';
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}