题解 题解 (2025)第十三届重庆市大学生程序设计竞赛 Lazy_boy_ 2025-05-12 2025-05-13 codeforces补题链接
题面链接
A
题目描述
给定一个长度为 $n$ 的一个数组$A$,对于数组$A$会有$T$轮操作,第$i$轮操作操作如下:
$A_{j} \gets A_{i} | A_{(i+j) \mod n}$
经过多少轮,可以使得这个数组所有数相同?
解题思路
将数拆分为二进制,对于每个数的某一位,至少存在一个 $1$, 进行一次操作,可产生一个 $1$, 第二次操作可产生两个$1$,依次进行,可产生$1 + 1 + 2 + 3 + \cdots + i$个 $1$,那么我们就可以暴力枚举一下,复杂度为$O(n \sqrt(n))$
起始也可以大胆猜想下,至多执行 $\log_{2}n$ 次就可以使得数组的数相同。
参考代码
#include <bits/stdc++.h> #define int long long #define pii std::pair<int ,int> void solve () { int n; std::cin >> n; std::vector<int > a (n) ; for (int i = 0 ; i < n; i ++) { std::cin >> a[i]; } for (int i = 0 ;i <= 500 ; i ++) { for (int j = 0 ; j < n; j ++) { a[j] |= a[(j + i) % n]; } bool f = false ; for (int j = 0 ; j < n - 1 ;j ++) { if (a[j] != a[j + 1 ]) { f = true ; break ; } } if (!f) { std::cout << i << std::endl; return ; } } } signed main () { std::ios::sync_with_stdio (false ); std::cin.tie (nullptr ), std::cout.tie (nullptr ); int T = 1 ; std::cin >> T; while (T --) solve (); }
C
题目描述
给出数字$n$,构造一个$n \times n$的方格图,方格中划分区域,每个区域的颜色相同,相邻区域的颜色不同,现在要用最少的颜色填土涂区域。
问:如何填涂可以使得所用的最少颜色数最大?
解题思路
要使得最少的颜色数最大,无非就是以下方式填涂:
$(1,2),(1,3), \cdots , (1,n), (2,1), (2,3), \cdots , (n, n-1)$
就是让$1~n$中的数两个相邻。
还有一种思路就是对于每一行的构造,我们可以将$1~n$的上升序列进行$i$的右移($i$代表行数)
这样的移动满足题面要求的期望还是极高的, 正解为第一种,第二种期望值较高,也可满足(不要问我为什么知道,问就是打表发现的)
参考代码
#include <bits/stdc++.h> #define int long long #define pii std::pair<int ,int> void solve () { int n; std::cin >> n; std::vector<int > a (n) ; std::iota (a.begin (), a.end (), 1ll ); for (int i = 0 ; i < n;i ++) { std::rotate (a.begin (), a.begin () + i, a.end ()); for (int j = 0 ; j < n; j ++) { std::cout << a[j] << " \n" [j == n - 1 ]; } } } signed main () { std::ios::sync_with_stdio (false ); std::cin.tie (nullptr ), std::cout.tie (nullptr ); int T = 1 ; std::cin >> T; while (T --) solve (); }
F
题面描述
给出三个数$a, b, c$,根据三个数的大小关系输出:
$a > b$ ,输出$Win$;
$a \le b , c > b$ ,输出$WIN$
$a \le b , c \le b$,输出$nowin$
参考代码
#include <bits/stdc++.h> #define int long long #define pii std::pair<int ,int> void solve () { int a, b, c; std::cin >> a >> b >> c; std::cout << (a > b ? "Win" : (c > b ? "WIN" : "nowin" )) << std::endl; } signed main () { std::ios::sync_with_stdio (false ); std::cin.tie (nullptr ), std::cout.tie (nullptr ); int T = 1 ; std::cin >> T; while (T --) solve (); }
H
题目描述
给出三个长度为$n$的数组$A,B,C$,数组$A,B$是长度为$n$的排列,代表一个盒子中的上边界和下边界小球的排序,数组$C$代表上边界小球是否靠边($C_{i}=0 \to$ 小球$i$不靠上边界,反之,则靠上边界)。
现在需要将编号相同的小球用绳子连起来(绳子是可任意变换形状的,长度也是任意长度的,绳子不可越出盒子边界),若绳子相交,则输出$No$,否则输出$Yes$。
解题思路
既然绳子是任意长度的,那么对于上边界没有靠边的球,可以直接连接起来,就算中间有靠边界的球相连,总有方式绕过。
那么,只剩下靠上边界的球需要考虑,不难发现上下边界的球需要序列相同才能满足相连不相交。
那么就只需要处理出那些球紧靠上边界即可
参考代码
#include <bits/stdc++.h> #define int long long #define pii std::pair<int ,int> void solve () { int n; std::cin >> n; std::vector<int > a (n) , b (n) , c (n) , x, y ; for (int i = 0 ; i < n; i ++) std::cin >> a[i]; for (int i = 0 ; i < n; i ++) std::cin >> b[i]; for (int i = 0 ; i < n; i ++) std::cin >> c[i]; std::set<int >se; for (int i = 0 ; i < n; i ++) { if (c[i]) x.push_back (a[i]), se.insert (a[i]); } for (int i = 0 ; i < n; i ++) { if (se.count (b[i]) ) { y.push_back (b[i]); } } std::cout << (x == y ? "Yes" : "No" ) << std::endl; } signed main () { std::ios::sync_with_stdio (false ); std::cin.tie (nullptr ), std::cout.tie (nullptr ); int T = 1 ; std::cin >> T; while (T --) solve (); }
L
题目描述
模拟一个栈的操作,操作$n$次,操作如下:
Push $x$: 将$x$压入栈。
Pop: 弹出栈顶元素。
Repeat: 将此前的操作重复,不包含当前操作。
每次操作都输出栈的元素总和,结果$ \mod 998244353$。
$1 \le n \le 2 \times 10^5, 0 \le x \le 998244353$
解题思路
首先模拟操作即可,但需要注意,当栈的大小大于 $2 \times 10^5$时,就不需要执行Repeat操作,斌且需要用数组模拟栈。
参考代码
#include <bits/stdc++.h> #define int long long #define pii std::pair<int ,int> const int MOD = 998244353 ;void solve () { int n, res = 0 ; std::cin >> n; std::deque<int > q; for (int i = 0 ; i < n; i ++) { std::string s; std::cin >> s; if (s == "Push" ) { int x; std::cin >> x; q.push_back (x); res = (res + x + MOD) % MOD; }else if (s == "Pop" ) { res = (res - q.back () + MOD) % MOD; q.pop_back (); }else { res = (((res + res)%MOD) + MOD) %MOD; if (q.size () < 2e5 ) { int t = q.size (); for (int i = 0 ; i < t; i ++) { q.push_back (q[i]); } } } std::cout << res % MOD << std::endl; } } signed main () { std::ios::sync_with_stdio (false ); std::cin.tie (nullptr ), std::cout.tie (nullptr ); int T = 1 ; while (T --) solve (); }