Codeforces Round 959 (Div. 1 + Div. 2 ABCDEFG 题) 文字讲解+视频讲解

Problem A. Diverse Game

Statement

给定 n × m n\times m n×m 的矩形 a a a a a a 中的每一个数均在 1 ∼ n m 1\sim nm 1nm 之间且互不相同。求出 n × m n\times m n×m 的矩形 b b b b b b 中的每一个数均在 1 ∼ n m 1\sim nm 1nm 之间且互不相同,同时 a i , j ≠ b i , j a_{i,j}\ne b_{i,j} ai,j=bi,j

Solution

注意到 a a a 如果拉长为一个序列,则是一个长为 n m nm nm 的排列。故,如果直接翻转 a a a,则长度为偶数的时候是可行的;长度为奇数的时候,中间的位置没变,只需将第一个位置与中间的位置交换即可。

Code

void solve() {int n, m, x;cin >> n >> m;std::vector<int> opt;for (int i = 1; i <= n * m; i ++) cin >> x, opt.push_back(x);if (n * m == 1) {cout << -1 << endl;return;}reverse(opt.begin(), opt.end());if (opt.size() & 1) swap(opt[0], opt[opt.size() / 2]);for (int i = 1; i <= n * m; i ++) {cout << opt[i - 1] << " ";if (i % m == 0) cout << endl;}
}

Problem B. Fun Game

Statement

给定一个长为 n n n 的二进制序列,接下来可以进行无限次操作:

  • 选择 l , r l,r l,r,将 s i s_i si 变为 s i − l + 1 ⊕ s i s_{i-l+1}\oplus s_i sil+1si

确定是否能从 s s s 序列变为 t t t 序列。

Solution

考察 s s s 中第一个出现 1 1 1 的位置,那么后面需要翻转的位置一定可以通过这个 1 1 1 来翻转状态。形式化的,若需要变换的位置为 i i i,第一次出现的位置为 j j j,则选择区间 l = i − j + 1 , r = i l=i-j+1,r=i l=ij+1,r=i 即可在不改变其他位置的前提下(因为 j j j 前面全为 0 0 0),翻转 i i i 位置。最后 j j j 位置自己异或自己即可。

但是如果前面存在 i i i,使得 s i = 0 , t i = 1 s_i=0,t_i=1 si=0,ti=1,则必然不存在方案,输出 NO;反之输出 YES

Code

void solve() {int n;string s, t;cin >> n >> s >> t;bool ok = 0;for (int i = 0; i < n; i ++) {if (s[i] == '0' && t[i] == '1') {cout << "NO" << endl;return;}if (s[i] == '1') {cout << "YES" << endl;return;}}cout << "YES" << endl;
}

Problem C. Hungry Games

Statement

给定长为 n n n 的序列 a a a 以及变量 g g g(初始为 0 0 0),选择 l , r l,r l,r,依次遍历 l ∼ r l\sim r lr 中的每一个数, g = g + a i g=g+a_i g=g+ai,若 g > x g>x g>x,则令 g = 0 g=0 g=0。问存在多少个 l , r l,r l,r 使得最终 g g g 的值不为 0 0 0

Solution

考虑枚举每一个 l l l,那么第一个使得 g g g 0 0 0 的位置可以轻松通过二分得出(令其为 k k k),则 l ∼ k − 1 l\sim k-1 lk1 的位置均可以作为右端点。那么 k + 1 ∼ n k+1\sim n k+1n 有哪些位置可以作为右端点呢?注意到 k k k 位置 g g g 0 0 0,即和 l ′ = k l'=k l=k 时初始状态时相同的,也就是 l ′ = k l'=k l=k 的所有可行的右端点, l l l 位置均可以。

故,列出转移方程: f l = f k + ( k − l ) f_l=f_k+(k-l) fl=fk+(kl)。时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn) log ⁡ \log log 来源于找 k k k

Code

void solve() {cin >> n >> x;for (int i = 1; i <= n; i ++)cin >> a[i], a[i] += a[i - 1];for (int i = n; i >= 1; i -- ) {int l = i, r = n, res = -1;while (l <= r) {int mid = l + r >> 1;if (a[mid] - a[i - 1] > x) r = mid - 1, res = mid;else l = mid + 1;}if (res == -1) dp[i] = n - i + 1;else dp[i] = dp[res + 1] + res - i;}int res = 0;for (int i = 1; i <= n; i ++) res += dp[i];cout << res << endl;for (int i = 1; i <= n; i ++) dp[i] = 0;
}

Problem D. Funny Game

Statement

给定 n n n 个点以及序列 a a a,接下来有若干次操作:

  • 选择 u , v u,v u,v,其中 ∣ a u − a v ∣ |a_u-a_v| auav x x x 的倍数,连接 u , v u,v u,v

通过进行 n − 1 n-1 n1 次操作,是否能将 n n n 个点连接成为一棵树,是则输出方案。

Solution

观察 Observation

观察样例发现全部均是 YES,回想抽屉原理的一个应用即为证明存在性。

深入探究 Investigate Deeply

∣ a u − a v ∣ |a_u-a_v| auav x x x 的倍数等价于 a u ≡ a v ( m o d x ) a_u\equiv a_v\pmod x auav(modx),考虑倒序操作,则进行第 x x x 次操作前有 x + 1 x+1 x+1 个连通块,即可选的数有 x + 1 x+1 x+1 个,而对 x x x 取模后可行的数只有 x x x 个,通过抽屉原理,不管前面如何操作,此时必然有至少 1 1 1 a u ≡ a v ( m o d x ) a_u\equiv a_v\pmod x auav(modx),通过并查集找出即可。

综上所述,答案永远都是存在的!

Code

int find(int x) {if (par[x] != x) par[x] = find(par[x]);return par[x];
}
void solve() {cin >> n;for (int i = 1; i <= n; i ++ ) cin >> a[i];for (int i = 1; i <= n; i ++) par[i] = i;for (int i = n - 1; i >= 1; i --) {for (int j = 1; j <= n; j ++) pos[a[j] % i].push_back(j);for (int j = 0; j < n; j ++) {sort(pos[j].begin(), pos[j].end(), [&](int a, int b) { return find(a) < find(b); });if (pos[j].size() <= 1) continue;if (find(pos[j][0]) != find(pos[j].back())) {par[find(pos[j][0])] = find(pos[j].back());res.emplace_back(pos[j][0], pos[j].back());break;}}for (int j = 0; j < n; j ++) pos[j].clear();}reverse(res.begin(), res.end());cout << "YES" << endl;for (auto v : res) cout << v.fi << " " << v.se << endl;res.clear();
}

Problem E. Wooden Game

Statement

给定 k k k 棵树,第 i i i 棵树有 n i n_i ni 个节点,每次可以将任意一棵树的一个子树删除,最终的权值即为删除的子树的大小按位或和

Solution

观察 Observation

简化:如果只有 1 1 1 棵树,则答案必为这棵树的大小。

证明:对于 x 1 + x 2 + ⋯ + x k = n x_1+x_2+\dots +x_k = n x1+x2++xk=n,则 x 1 ∣ x 2 ∣ … ∣ x k ≤ n x_1|x_2|\dots |x_k\le n x1x2xkn。所以这说明对于一棵树,至多只存在一个子树给答案是有贡献的,而一棵树便是特殊情况,必然是这棵树的大小

深入探究 Investigate Deeply

从观察中得出,一棵树只有一个子树给答案是有贡献的,考察这棵子树的大小取值范围,由于可以不断地删除叶子节点取剩余部分,所以大小地取值范围为 [ 1 , n i ] [1,n_i] [1,ni]

问题转化为给定 k k k 个变量 x x x,第 i i i 个变量的取值范围为 [ 1 , n i ] [1,n_i] [1,ni],求 max ⁡ ( x 1 ∣ x 2 ∣ … ∣ x k ) \max(x_1|x_2|\dots |x_k) max(x1x2xk)。故变为了二进制的问题,使用经典方式拆位,对于第 i i i 位:

  • 如果存在大于等于 2 2 2 n j n_j nj 使得第 i i i 位为 1 1 1,则一个 n i n_i ni 将这一位变为 1 1 1,其余的只需这一位取 0 0 0,后面所有位取 1 1 1 即可。

  • 如果存在恰好 1 1 1 n j n_j nj 使得第 i i i 位为 1 1 1,则只需将第 i i i 位变为 1 1 1 即可。

Code

void solve() {cin >> n;for (int i = 1; i <= n; i ++) {cin >> a[i];int x;for (int j = 2; j <= a[i]; j ++) cin >> x;}for (int i = 1; i <= n; i ++)for (int j = 0; j < 30; j ++) cnt[j] += (a[i] >> j & 1);int res = 0;for (int i = 30; i >= 0; i --) {if (cnt[i] >= 2) res |= ((1ll << i) - 1) | (1ll << i);else if (cnt[i] == 1) {res |= (1ll << i);}}cout << res << endl;for (int i = 0; i <= 30; i ++) cnt[i] = 0;
}

Problem F. Stardew Valley

Statement

给定 n n n 个点 m m m 条边的无向图,边权为 1 1 1 的边必须选,边权为 0 0 0 的边可选可不选。求该图上的一条欧拉回路(经过选过的边恰好 1 1 1 次)

Solution

观察 Observation

由于欧拉回路的判定方式为所有点的度数均为偶数,故问题转化为在选择边权为 1 1 1 的边,每个点的度数的奇偶性组成 01 01 01 序列。现在可以加入若干条边,使得两个端点的奇偶性可以异或 1 1 1。给出 1 1 1 种选择方案,将选出的边加入后跑欧拉回路即可解决问题。

深入探究 Investigate Deeply

上述问题与 ABC155F - Perils in Parallel 化为 1 1 1 道题,具体过程此处不再赘述。

聪明的人能看到事物之间的联系,更聪明的人能看到联系之间的联系。

Code

void add(int a, int b) {e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void dfs(int u) {st[u] = d[u], vis[u] = true;for (auto v : g[u]) {if (vis[v]) continue;dfs(v);st[u] ^= st[v];if (st[v]) add(u, v), add(v, u);}
}
void Euler_Path(int u) {for (int &i = h[u]; ~i;) {if (has[i]) { i = ne[i]; continue; }int j = e[i];has[i ^ 1] = true, i = ne[i], Euler_Path(j);}res.push(u);
}void solve() {cin >> n >> m;for (int i = 1; i <= n; i ++) h[i] = -1, vis[i] = 0, st[i] = 0, d[i] = 0, g[i].clear();while (m -- ) {int u, v, c;cin >> u >> v >> c;if (!c) g[u].emplace_back(v), g[v].emplace_back(u);else add(u, v), add(v, u), d[u] ^= 1, d[v] ^= 1;}for (int i = 1; i <= n; i ++)if (!vis[i]) {dfs(i);if (st[i]) {cout << "NO" << endl;return;}}Euler_Path(1);cout << "YES" << endl;cout << res.size() - 1 << endl;while (res.size()) cout << res.top() << " ", res.pop();cout << endl;
}

Problem G. Minecraft

Statement

给定目标 01 01 01 s s s n n n 01 01 01 a i a_i ai,求出 01 01 01 x x x 使得 ∑ a i ⊕ x = s \sum a_i\oplus x=s aix=s 01 01 01 串的长度均为 k k k

1 ≤ n , k ≤ 2 × 1 0 6 1\le n,k\le 2\times 10^6 1n,k2×106 1 ≤ n ⋅ k ≤ 2 × 1 0 6 1\le n\cdot k\le 2\times 10^6 1nk2×106

Solution

观察 Observation

二进制问题——拆位,考虑对于每一位与 s s s 匹配的方案,不过注意到存在加法,所以需要同时处理进位问题。对于第 i i i 位,这一位上填的 1 1 1 的个数不会超过 2 n 2n 2n,所以可以直接存储( 1 ≤ n ⋅ k ≤ 2 × 1 0 6 1\le n\cdot k\le 2\times 10^6 1nk2×106

深入探究 Investigate Deeply

f i , j f_{i,j} fi,j 表示前 i i i 位,第 i i i 位填了 j j j 1 1 1 是否可行。考虑转移:
{ f i , ⌊ j 2 ⌋ + c n t i ← f i + 1 , j ⌊ j 2 ⌋ + c n t i m o d 2 = s i f i , ⌊ j 2 ⌋ + n − c n t i ← f i + 1 , j ⌊ j 2 ⌋ + n − c n t i m o d 2 = s i \begin{cases} &f_{i,\lfloor\frac{j}{2}\rfloor+\mathrm{cnt}_i}\leftarrow f_{i+1,j} \qquad \lfloor\frac{j}{2}\rfloor+\mathrm{cnt}_i\bmod 2 = s_i\\ &f_{i,\lfloor\frac{j}{2}\rfloor+n-\mathrm{cnt}_i}\leftarrow f_{i+1,j}\qquad \lfloor\frac{j}{2}\rfloor+n-\mathrm{cnt}_i\bmod 2 = s_i \end{cases} {fi,2j+cntifi+1,j2j+cntimod2=sifi,2j+ncntifi+1,j2j+ncntimod2=si
第一种情况即为当前位 x x x 0 0 0,第二种情况为当前位 x x x 1 1 1。从 i + 1 i+1 i+1 转移过来的原因主要是要从低位向高位做(因为进位是从低位向高位的)。

Code

void solve() {int n, k;cin >> n >> k;char x;std::vector<int> s(k), cnt(k, 0);std::vector<vector<int>> a(n + 1, vector<int>(k)), dp(k, vector<int>(2 * n + 1, 0));std::vector<vector<array<int, 3>>> pre(k, vector<array<int, 3>>(2 * n + 1));for (int i = 0; i < k; i ++) cin >> x, s[i] = x & 1;for (int i = 1; i <= n; i ++) for (int j = 0; j < k; j ++) cin >> x, a[i][j] = x & 1, cnt[j] += a[i][j];if ((cnt[k - 1] & 1) == s[k - 1]) dp[k - 1][cnt[k - 1]] = 1;if ((n - cnt[k - 1] & 1) == s[k - 1]) dp[k - 1][n - cnt[k - 1]] = 1;for (int i = k - 2; i >= 0; i --)for (int j = 0; j <= 2 * n; j ++) {if (!dp[i + 1][j]) continue;int put1 = ((j >> 1) + cnt[i] & 1), put2 = ((j >> 1) + n - cnt[i] & 1);if (put1 == s[i]) dp[i][(j >> 1) + cnt[i]] |= dp[i + 1][j], pre[i][(j >> 1) + cnt[i]] = {i + 1, j, 0};if (put2 == s[i]) dp[i][(j >> 1) + n - cnt[i]] |= dp[i + 1][j], pre[i][(j >> 1) + n - cnt[i]] = {i + 1, j, 1};}if (!dp[0][s[0]]) cout << -1 << endl;else {PII lst = {0, s[0]};std::vector<int> res;while (lst.fi != k - 1) {res.push_back(pre[lst.fi][lst.se][2]);lst = {pre[lst.fi][lst.se][0], pre[lst.fi][lst.se][1]};}if (lst.se == cnt[k - 1]) res.push_back(0);else res.push_back(1);for (auto v : res) cout << v;cout << endl;}
}

视频讲解 Video Tutorial

Codeforces Round 959 sponsored by NEAR (Div. 1 + Div. 2)(A ~ G 题讲解)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/47139.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp,vue3上传图片组件封装

首先创建一个 components 文件在里面进行组件的创建 下面是 vip组件的封装 也就是图片上传组件 只是我的命名是随便起的 <template><!--图片 --><view class"up-page"><!--图片--><view class"show-box" v-for"(item,ind…

蓝桥杯Python算法竞赛常用的函数库

博客主页&#xff1a;音符犹如代码系列专栏&#xff1a;Python关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ ​ 目录 math collectcions heapq functool itertools 常用的库函数 m…

开源的语音合成工具_ChatTTS_用法及资源

1 引言 5 月开源的 ChatTTS&#xff0c;最近文章十篇里有五篇以上都在讨论它。很多新的 TTS 模型也用它来做比较。感觉没用过 ChatTTS 都不敢评测其他的。 目前&#xff0c;ChatTTS 支持英文和中文。在 arxiv 上没找到相关论文&#xff0c;所以本文主要评测使用感受。 &…

web服务器1

&#xff08; 1 &#xff09;仅提供用户浏览的单向静态网页 单纯是由服务器单向提供数据给客户端&#xff0c; Server 不需要与 client 端有互动&#xff0c;所以你可以到该网站上去浏 览&#xff0c;但是无法进行数据的上传。 &#xff08; 2 &#xff09;提供用户互动接口的…

深入理解Linux网络(三):TCP对象创建

深入理解Linux网络&#xff08;三&#xff09;&#xff1a;TCP对象创建 TCP对象创建inet_createsock_init_data TCP对象创建 常见的三句TCP编程&#xff1a; int main() {int sk socket(AF_INET, SOCK_STREAM, 0);connect(sk, ...)recv(sk, ...) }简单的两三⾏代码&#xff…

十年前的老电脑能装win10吗_十年前的老电脑用U盘安装win10教程

十年前的老电脑能装win10吗&#xff1f;十年前的老电脑只要满足win10最低要求的配置都可以安装win10。安装win10方法很多&#xff0c;有一键重装方法、U盘安装、硬盘安装等方式&#xff0c;但最靠谱的方式还是U盘安装。十年前的老电脑用U盘安装win10首先要将u盘制作成u盘启动盘…

react自定义校验报错问题修复 ProFormText

1、以下是tsx组件 自定义校验告警导致表单无法提交问题修复 修改如下&#xff1a;

体态识别开发记录

1.多标签输出分类算法 https://aiuai.cn/aifarm1372.html 2.体态识别算法 体态对比 体态判断 2.1 3D建模的方案 stable diffusion 插件地址&#xff1a; ControlNet https://github.com/Mikubill/sd-webui-controlnet 3D Openpose https://github.com/nonnonstop/sd…

VsCode SSH远程连接服务器【内网穿透公网连接】

文章目录 1.前言2.VS code的安装和设置2.1 VS code的下载安装2.2 OpenSSH的启用2.3 为VS code配置ssh2.4 局域网内测试VS code的ssh连接2.5 Cpolar下载安装 3.Cpolar端口设置3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 1.前言 记得笔者小时候看电视&#xff…

速盾:cdn除了网站还有哪些应用?

CDN&#xff08;内容分发网络&#xff09;是一种通过将内容分布到离用户更近的服务器上&#xff0c;以提供更快速、可靠的内容传输的技术。虽然CDN最初被广泛用于网站和静态内容的传输&#xff0c;但随着技术的进步&#xff0c;它已经应用于更广泛的领域。下面是一些CDN除了网站…

仿源码大师主界面UI的iAPP源文件

仿源码大师首页主界面的布局 首页&#xff0c;分类&#xff0c;需求&#xff0c;我的 就只有这几个界面内容而已 资源静态 没有任何动画和功能 纯UI布局 纯UI布局 他的最新版已经不是这个UI布局 放心使用 以学习参考为目的&#xff0c;如有不妥望告知 原创&#xff0c;纯…

vue-virtual-scroll-list 虚拟滚动,解决数组大量卡顿问题

vue-virtual-scroll-list - npm npm install vue-virtual-scroll-list --save 参数&#xff1a; :data-key"某一行唯一标识符" :data-sources"列表数据" :data-component"单行数据需要展示的内容" :keeps"虚拟列表在在页面展示的数量&quo…

【Java数据结构】线性表之栈和队列

栈&#xff08;Stack&#xff09; 简单描述 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&…

初识网络基础知识

关于网络的一些核心概念 局域网 局域网&#xff08;Local Area Network&#xff0c;简称LAN&#xff09;是一种计算机网络&#xff0c;覆盖的范围通常是相对较小的地理区域&#xff0c;比如一个办公室、一栋大楼或一个校园。 局域网的组成通常包括以下部分&#xff1a; 网络…

数据结构-C语言-排序(3)

代码位置&#xff1a;test-c-2024: 对C语言习题代码的练习 (gitee.com) 一、前言&#xff1a; 1.1-排序定义&#xff1a; 排序就是将一组杂乱无章的数据按照一定的规律&#xff08;升序或降序&#xff09;组织起来。(注&#xff1a;我们这里的排序采用的都为升序) 1.2-排序分…

录取查询老师在哪里制作?

随着考试的落幕&#xff0c;家长们焦急等待的心情终于可以稍微缓解&#xff0c;因为录取结果即将揭晓。然而&#xff0c;对于老师来说&#xff0c;这仅仅是另一项繁重工作的开始。他们需要将每一份录取通知单逐一发送给学生家长&#xff0c;这个过程不仅耗时而且容易出错。面对…

Blender中的重拓扑修改器如何使用?

许多人还不了解Blender中的重拓扑编辑器及其使用方法。Blender中的重拓扑修改器提供了一系列工具和选项&#xff0c;以简化创建优化网格的过程&#xff0c;无论是出于何种目的&#xff0c;都能为3D艺术家和建模者节省大量时间和精力。那么&#xff0c;在Blender中重拓扑的定义是…

《数据结构:C语言实现双链表》

文章目录 一、链表的分类二、双向链表1、概念与结构 三、双向链表实现1、双向链表要实现的功能2、哨兵位初始化3、双链表头插数据4、判断链表是否为空5、打印链表数据6、尾插数据7、头删数据8、尾删数据9、寻找数据所在结点10、在任意结点之后插入数据11、删除任意结点12、销毁…

FastGPT 代码调试配置

目录 一、添加 launch.json 文件 二、调试 本文简单介绍如何通过 vscode 对 FastGPT 进行调试。 这里假设已经安装 vsocde 和 FastGPT本地部署。 一、添加 launch.json 文件 vscode 打开 FastGPT 项目&#xff0c;点击 调试 -> 显示所有自动调试配置 -> 添加配置 -&…

使用 Vue 和 ECharts 打造动态数据可视化图表

大家好&#xff0c;今天我们来聊聊如何使用 Vue 和 ECharts 来创建动态数据可视化图表。Vue 是一个渐进式的 JavaScript 框架&#xff0c;非常适合构建用户界面。而 ECharts 是一个强大的开源图表库&#xff0c;能够帮助我们轻松创建各种类型的图表。将这两者结合起来&#xff…