Codeforces Round 919 (Div. 2) A~E

A. Satisfying Constraints(模拟)

题意:

给出 n n n个限制条件,问有多少个数字 k k k同时满足这些限制条件。

限制条件分为以下三种:

  1. k k k必须大于等于给出的一些数字 x x x

  2. k k k必须小于等于给出的一些数字 x x x

  3. k k k不能与给出的数字 x x x相同

分析:

对于限制条件1, 2,可以使用两个变量维护数字 k k k的取值区间。

对于限制条件3,可以采用容器(set, map等)存储这些不能取到的数字。

根据限制条件1,2得到的区间,再遍历容器检查区间内有多少数字不能被取到,剩下的数字个数就是答案。

代码:

#include<bits/stdc++.h>using namespace std;
typedef long long ll;set<int> s;void solve() {int n;cin >> n;int l = -1e9, r = 1e9;s.clear();for (int i = 0; i < n; i++) {int a, x;cin >> a >> x;if (a == 1) {l = max(l, x);} else if (a == 2) {r = min(r, x);} else {s.insert(x);}}int ans = r - l + 1;for (auto i : s) {if (i >= l && i <= r) ans--;}cout << max(0, ans) << endl;
}int main() {int Case;cin >> Case;while (Case--) {solve();}return 0;
}

B. Summation Game(枚举)

题意:

有一个包含 n n n个数字的序列 A = a 1 , a 2 , . . . , a n A = a_1, a_2, ..., a_n A=a1,a2,...,anAliceBob将会执行以下操作:

  • 首先,Alice将会移除序列中至多 k k k个数字。

  • 然后,Bob将会选择剩余的序列中至多 x x x个数字并让这些数字乘上 − 1 -1 1

Alice想让剩下的数字之和尽可能大,但Bob想让剩下的数字之和尽可能小,假设两人均采取最优策略,那么剩下的数字之和会是多少?

分析:

实际上,Bob会做的事情是固定的,即选择剩余的数组中最大的 x x x个数字进行操作。

既然Bob的操作固定了,那就可以思考Alice的操作了,由于Alice想要结果尽可能大,那么Alice的操作就是删除部分最大的数字,由于不知道删除多少个是最优的,因此需要对删除的数字个数进行枚举,记录最大的结果。

对删除后剩余的数字总和进行计算可以先对数组进行排序,并维护前缀和,使用前缀和来计算结果。

hint: 删除元素后剩余的数字不足 x x x个时,计算区间和时需避免出现下标越界。

代码:

#include<bits/stdc++.h>using namespace std;
typedef long long ll;
const int N = 2e5 + 5e2;
int a[N], pre[N];void solve() {int n, k, x;cin >> n >> k >> x;for (int i = 1; i <= n; i++) {cin >> a[i];}sort(a + 1, a + n + 1);for (int i = 1; i <= n; i++) {pre[i] = pre[i - 1] + a[i];}int ans = -1e9;for (int i = 0; i <= k; i++) {int m = n - i;int sum;/*小心下标越界*/if (m > x) sum = pre[m - x] - (pre[m] - pre[m - x]);else sum = -pre[m];ans = max(ans, sum);}cout << ans << endl;
}int main() {int Case;cin >> Case;while (Case--) {solve();}return 0;
}

C. Partitioning the Array(数学)

题意:

给出一个包含 n n n个数字的数组 A = a 1 , a 2 , . . . , a n A = a_1, a_2, ..., a_n A=a1,a2,...,an,你可以选择一个数字 k k k,并对数字进行以下操作:

  • 将数组均分为 n k \frac{n}{k} kn个子数组,子数组形如: [ a 1 , a 2 , . . . , a k ] , [ a k + 1 , a k + 2 , . . . , a 2 k ] , . . . , [ a n − k + 1 , a n − k + 2 , . . . , a n ] [a_1, a_2, ..., a_k], [a_{k + 1}, a_{k + 2}, ..., a_{2k}], ..., [a_{n - k + 1}, a_{n - k + 2}, ..., a_n] [a1,a2,...,ak],[ak+1,ak+2,...,a2k],...,[ank+1,ank+2,...,an]

  • 如果可以选择一个数字 m m m,让数组中所有元素对 m m m取余数,且计算后得到的各个子数组均是相同的,那么就可以获得一点积分。

问:最多可以获得多少积分(一个数字 k k k最多产生一点积分)。

分析:

首先思考 k k k的选择,不难发现只有 k k k n n n的因子时各个子数组的长度才是相等的,因此只需要考虑 n n n的所有因子作为 k k k的选择。

当只有两个数字 x , y x, y x,y时,那么只要这两个数之间差的绝对值取模 m m m的结果为0,那么这两个数字对于 m m m取模的结果必然是相同的。

将结论推广至全部数组中的内容,为了尽可能使得到的 m m m更大,令 m m m即为所有子数组中对位元素的差的绝对值之间的最大公约数。

为了便于计算,每次计算只考虑相邻子数组中的元素进行对位计算,即计算:

m = g c d ( ∣ a 1 − a 1 + k ∣ , ∣ a 2 − a 2 + k ∣ , . . . , ∣ a n − k + 1 − a n ∣ ) m = gcd(|a_1 - a_{1 + k}|, |a_2 - a_{2 + k}|, ..., |a_{n - k + 1} - a_n|) m=gcd(a1a1+k,a2a2+k,...,ank+1an)

由于题目要求的 m ≥ 2 m \ge 2 m2,那么只要得到的结果不为1,那么就表示当前存在合法的 m m m能获得积分。

Tips: 当数组中对位元素之差均为0时,即各子数组中相同位置的元素均相等,此时得到的最大公约数为 0 0 0,但此时任选一个 m m m均为合法的解,因此也可以获得积分。

代码:

#include<bits/stdc++.h>using namespace std;
typedef long long ll;
const int N = 2e5 + 5e2;
int a[N];void solve() {int n;cin >> n;for (int i = 1; i <= n; i++) {cin >> a[i];}int ans = 0;for (int k = 1; k <= n; k++) {if (n % k == 0) {int m = 0;for (int j = 1; j + k <= n; j++) {m = __gcd(m, abs(a[j + k] - a[j]));}if (m != 1) ans++;//m>=2 || m == 0}}cout << ans << endl;
}int main() {int Case;cin >> Case;while (Case--) {solve();}return 0;
}

D.Array Repetition(模拟)

题意:

开始时有一个空的数组 a a a,将对这个数组进行 n n n次操作,每次操作为以下两种操作之一:

  1. 选择一个数字 x x x,将这个数字添加到数组 a a a的末尾。

  2. 将数组 a a a的内容复制 x x x遍放在数组 a a a的后面。

结束操作后,会给出 q q q个询问,每个询问需要你回答数组中第 k k k个元素是多少。

分析:

虽然操作 2 2 2会使数组中数字总数增加的非常快,但是由于题目的询问最多只会到 1 0 18 10^{18} 1018,因此,当数组中总数超过 1 0 18 10^{18} 1018时,就不需要再进行操作了。

可以使用结构体记录下每次操作后数组中的数字总数 s u m sum sum以及操作 1 1 1添加进来的数字个数 c n t cnt cnt。如果是操作 2 2 2,还需要记录下操作 2 2 2的复制次数 m u l mul mul

对于操作 1 1 1,还需将添加的数字记录到另一个数组 a a a中。

然后对于每次查询,均可通过递归的方式从记录的操作信息回推到某一条操作 1 1 1对应的数字:

  • 如果当前查询的第 k k k个元素与当前结构体记录的总数字个数 s u m sum sum相等,那么此时的答案就是数组 a a a中第 c n t cnt cnt个数字。

  • 如果不相等,说明需将本轮的复制操作消除,继续递归查找,将复制消除后,需将 k k k也修改为 k m o d s u m m u l k \text{ } mod \text{ } \frac{sum}{mul} k mod mulsum,而且需要注意,如果余数为 0 0 0,需要将 k k k修改为 s u m m u l \frac{sum}{mul} mulsum,计算得到 k k k后继续递归查询。

对于每次递归查询,遇到操作 1 1 1就会返回结果,遇到操作 2 2 2就会移除复制操作后递归查询,查询时间复杂度为对数级别。

坑点:

虽然我们手动设置数字上限为 1 0 18 10^{18} 1018,但如果使用long long类型存储,依然不能保证运算中不会发生溢出,因此需要使用__int128来进行存储。

代码:

#include<bits/stdc++.h>using namespace std;
typedef long long ll;
const int N = 2e5 + 5e2;
struct Node{__int128 sum;//数字总数int cnt, mul;//操作1的次数,mul为如果当前操作为操作2,那么记录复制的次数bool operator < (const Node &o) const {if (sum != o.sum) return sum < o.sum;return cnt < o.cnt;}
};int n, q;vector<int> a;//数字表
vector<Node> num;//信息表int search(ll k) {查询第k个数字//在信息表里查int id = lower_bound(num.begin(), num.end(), Node{k, 0}) - num.begin();//当前查询的k与信息表的数字总数相等,那么此时就是对应信息表中记录的最后一次操作1插入的数字if (num[id].sum == k) {return a[num[id].cnt - 1];}k %= num[id].sum / num[id].mul;//否则计算在当前的操作2前第k个数字对应的数字是第几个if (k == 0) k = num[id].sum / num[id].mul;return search(k);//递归查询
}void solve() {a.clear();num.clear();cin >> n >> q;__int128 sum = 0;int cnt = 0;for (int i = 0; i < n; i++) {ll b, x;cin >> b >> x;int mul = 0;if (sum <= 1e18) {//只有数字总数小于等于10的18次方才记录操作信息if (b == 1) {cnt++;sum++;a.push_back(x);} else {mul = x + 1;sum *= mul;//如果是long long类型,这里就可以发生溢出}num.push_back(Node{sum, cnt, mul});}}while (q--) {ll k;cin >> k;cout << search(k) << ' ';}cout << endl;
}int main() {int Case;cin >> Case;while (Case--) {solve();}return 0;
}

E. Counting Binary Strings(排列组合、dp)

题意:

对于一个只含有 0 0 0 1 1 1的字符串 s s s,如果它的子串 s ^ \hat{s} s^只含有 1 1 1 1 1 1,我们就称他为好子串。

现在我们希望知道,有多少个字符串 s s s满足以下要求:

  • s s s有且仅有 n n n个好子串;
  • s s s的好子串的长度均不超过 k k k

答案可能很大,需要对 998244353 998244353 998244353取模。另外,在考虑子串时,我们需要考虑位置。比如说,1010中,我们认为有 2 2 2个子串 10 10 10,因为他们的位置是不同的。

思路

对于由若干个 1 1 1 0 0 0组成的字符串 s s s,我们可以认为:每一个 1 1 1都可以和它之前、之后的 0 0 0进行组合,形成好字符串。比如:0010,对于这个 1 1 1,它可以分别向前、向后与若干个 0 0 0进行组合(当然也可以不向前选择、或者不想后选择)。在这个例子中,若我们不考虑 k k k的限制,含有中间的 1 1 1的子串有 3 × 2 = 6 3\times2=6 3×2=6个。类似的,00100010中含有 3 × 4 + 4 × 2 = 20 3\times4+4\times2=20 3×4+4×2=20个好子串。在这个过程中,我们重点关注的是1左右两边 0 0 0的个数(此处在计算过程中我们进行了 + 1 +1 +1操作)。

对于一个给定的字符串 s s s,我们可以把这些 0 0 0的个数 + 1 +1 +1以后的结果记作数组 a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1,a2,,an的内容,则 s s s中好子串的个数为 a 1 a 2 + a 2 a 3 + ⋯ + a n − 1 a n a_1a_2+a_2a_3+\dots+a_{n-1}a_n a1a2+a2a3++an1an。此时若我们多加入一个 a n + 1 a_{n+1} an+1,就是在原来结果的基础上加上 a n a n + 1 a_na_{n+1} anan+1。换言之,假设我们用 d p [ s u m ] dp[sum] dp[sum]数组中的元素来表示好子串个数为 s u m sum sum的子串数,即 s u m = ∑ i = 1 n + 1 a n sum=\sum_{i=1}^{n+1}a_n sum=i=1n+1an,那么我们可以发现: d p [ s u m ] dp[sum] dp[sum] d p [ s u m − a n ⋅ a n − 1 ] dp[sum-a_n\cdot a_{n-1}] dp[sumanan1]有关。

但是,并不是只有 a n a_n an结尾的方案才能得到和为 s u m sum sum的结果,我们需要给 d p dp dp数组加上一个维度作为限制。此处,我们以 d p [ s u m ] [ l a s t ] dp[sum][last] dp[sum][last]表示:和为 s u m sum sum,最后一个元素(即我们前面讨论的 a n + 1 a_{n+1} an+1)为 l a s t last last的方案数,那么我们有:

d p [ s u m ] [ l a s t ] = ∑ i d p [ s u m − i ⋅ l a s t ] [ i ] \begin{aligned} dp[sum][last]=\sum_{i}dp[sum-i\cdot last][i] \end{aligned} dp[sum][last]=idp[sumilast][i]

其中, i i i的枚举范围要考虑到:

  • i ⋅ l a s t ≤ s u m i\cdot last\le sum ilastsum,避免出现负数下标;
  • i + l a s t − 1 ≤ k i+last-1\le k i+last1k,这一举动是为了保证加入以后,长度不超过 k k k
    • 如果你不理解为什么要 − 1 -1 1,请你回想:我们在上面的计算过程中进行了 + 1 +1 +1操作,当你要对 a a a数组加入元素 l a s t last last时,实际上你是多加了好几个 0 0 0 i i i l a s t last last的数值如果代表长度,会包含同一个 1 1 1,计算长度时,我们要避免重复计算这个 1 1 1的长度,所以根据容斥原理进行 − 1 -1 1操作。

初始化 d p dp dp数组时,可以令满足 1 ≤ l a s t ≤ k 1\le last\le k 1lastk d p [ 0 ] [ l a s t ] dp[0][last] dp[0][last]均为 1 1 1,即对应全 0 0 0字符串。

hint: 清空 d p dp dp数组需要使用循环来清空避免超时。

代码:

#include<bits/stdc++.h>using namespace std;
int n, k, dp[3000][3000];
const int mod = 998244353;void solve() {cin >> n >> k;for (int i = 1; i <= n; i++) for (int j = 1; j <= k; j++) dp[i][j] = 0;int ans = 0;//对全0字符串进行初始化操作for (int last = 1; last <= k; last++) {dp[0][last] = 1;}//根据dp方程进行计算,注意i的范围,不要忘记取模for (int sum = 1; sum <= n; sum++) {for (int last = 1; last <= k; last++) {for (int i = 1; i * last <= sum && i + last - 1 <= k; i++) {dp[sum][last] = (dp[sum][last] + dp[sum - i * last][i]) % mod;}}}//统计满足要求的好子串个数,不要忘记取模for (int last = 1; last <= k; last++) {ans = (ans + dp[n][last]) % mod;}cout << ans << endl;
}int main() {int Case;cin >> Case;while (Case--) {solve();}return 0;
}

学习交流

以下为学习交流QQ群,群号: 546235402,每周题解完成后都会转发到群中,大家可以加群一起交流做题思路,分享做题技巧,欢迎大家的加入。

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

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

相关文章

定时器开发基础

1定时器的基本概述 通过滴漏和漏沙瓶这两个例子简单讲述定时器的基本工作原理。 STM32的常见的定时器资源&#xff1a; 系统嘀嗒定时器SysTick、看门狗定时器WatchDog、实时时钟RTC、基本定时器、通用定时器、高级定时器。 系统嘀嗒定时器SysTick &#xff1a;这是一个集成在C…

JavaScript 自定义分页组件

仿boostrap 前端分页组件的实现 一 写一个前端自定义分页组件&#xff0c;需要考虑以下问题 需要一个<ul id"pagination"></ul>标签 total; // 总数据的数量 pageSize; // 一页显示数量 pageIndex; // 当前页 二 实现细节 编写html文件 index.html…

蓝桥杯(C++ 整数删除 优先队列 )

优先队列&#xff1a; 优先队列具有队列的所有特性&#xff0c;包括队列的基本操作&#xff0c;只是在这基础上添加了内部的一个排序&#xff0c;它本质是一个堆实现的。 1.头文件&定义 #include <queue> #include <functional> //greater<>// 定义 p…

2023 年顶级前端工具

谁不喜欢一个好的前端工具&#xff1f;在本综述中&#xff0c;您将找到去年流行的有用的前端工具&#xff0c;它们将帮助您加快开发工作流程。让我们深入了解一下&#xff01; 在过去的 12 个月里&#xff0c;我在我的时事通讯 Web Tools Weekly 中分享了数百种工具。我为前端…

经典数据库练习题及答案

数据表介绍 --1.学生表 Student(SId,Sname,Sage,Ssex) --SId 学生编号,Sname 学生姓名,Sage 出生年月,Ssex 学生性别 --2.课程表 Course(CId,Cname,TId) --CId 课程编号,Cname 课程名称,TId 教师编号 --3.教师表 Teacher(TId,Tname) --TId 教师编号,Tname 教师姓名 --4.成绩…

JavaScript DOM可以做什么?

1、通过id获取标签元素 DOM是文档对象模型&#xff0c;它提供了一些属性和方法来方便我们操作document对象&#xff0c;比如getElementById()方法可以通过某个标签元素的id来获取这个标签元素 // 用法 window.document.getElementById(id); // 例子 <!DOCTYPE html> &l…

深度学习模型之yolov8实例分割模型TesorRT部署-python版本

1 模型转换 从github上下载官方yolov8版本&#xff0c;当前使用的版本是2023年9月份更新的版本&#xff0c;作者一直在更新。官网地址 2 加载模型 模型的训练和测试在官方文档上&#xff0c;有详细的说明&#xff0c;yolov8中文文档这里不做过多说明&#xff0c;v8现在训练是…

智能驾驶新浪潮:SSD与UFS存储技术如何破浪前行?-UFS篇

如果说SSD是赛道上的超级跑车&#xff0c;那UFS更像是专为智能汽车定制的高性能轻量化赛车。UFS采用串行接口技术&#xff0c;像是闪电侠一样&#xff0c;将数据传输的速度推向新高&#xff0c;大幅缩短了系统启动时间和应用程序加载时间&#xff0c;这对追求即时反应的ADAS系统…

从零开始的 dbt 入门教程 (dbt core 命令进阶篇)

引 根据第一篇文章的约定&#xff0c;我想通过接下来的几篇文章带大家进一步了解 dbt 的用法&#xff0c;原计划这篇文章我会介绍 dbt 命令的进阶用法&#xff0c;进一步认识 dbt 的配置以及如何创建增量表等等零零散散十几个方面的知识点&#xff0c;结果在我写完命令部分发现…

深度学习中Numpy的一些注意点(多维数组;数据类型转换、数组扁平化、np.where()、np.argmax()、图像拼接、生成同shape的图片)

文章目录 1多维数组压缩维度扩充维度 2numpy类型转换深度学习常见的float32类型。 3数组扁平化4np.where()的用法5np.argmax()6图像拼接7生成同shape的图片&#xff0c;指定数据类型 1多维数组 a.shape(3,2);既数组h3&#xff0c;w2 a.shape(2,3,2);这里第一个2表示axis0维度上…

奇异值分解(SVD)【详细推导证明】

机器学习笔记 机器学习系列笔记&#xff0c;主要参考李航的《机器学习方法》&#xff0c;见参考资料。 第一章 机器学习简介 第二章 感知机 第三章 支持向量机 第四章 朴素贝叶斯分类器 第五章 Logistic回归 第六章 线性回归和岭回归 第七章 多层感知机与反向传播【Python实例…

Dubbo-admin监控中心

监控中心 Dubbo-admin监控中心执行操作启动provider和consumer项目进行测试总体流程 Dubbo-admin监控中心 dubbo-admin下载路径 git clone https://github.com/apache/dubbo-admin.git图1-1 dubbo-admin项目文件展示 执行操作 # 启动zookeeper# 前端 cd dubbo-admin-ui npm i…

Linux 设备树详解

目录 1、概述 2、节点&#xff08; node&#xff09;和属性&#xff08; property&#xff09; 2.1、DTS 描述键值对的语法&#xff1a; 2.2 节点语法规范说明 2.3节点名及节点路径 2.4 节点别名&#xff08;节点引用&#xff09; 2.5 合并节点内容 2.6 替换节点内容 2…

java:流程控制

一、流程控制语句分类 顺序结构分支结构&#xff08;if&#xff0c;switch&#xff09;循环结构&#xff08;for&#xff0c;while&#xff0c;do...while&#xff09; 二、顺序结构 定义&#xff1a;顺序结构是程序中最基本的流程控制&#xff0c;没有特定的语法结构&#…

Sqoop故障排除指南:处理错误和问题

故障排除是每位数据工程师和分析师在使用Sqoop进行数据传输时都可能遇到的关键任务。Sqoop是一个功能强大的工具&#xff0c;但在实际使用中可能会出现各种错误和问题。本文将提供一个详尽的Sqoop故障排除指南&#xff0c;涵盖常见错误、问题和解决方法&#xff0c;并提供丰富的…

HarmonyOS4.0系列——07、自定义组件的生命周期、路由以及路由传参

自定义组件的生命周期 允许在生命周期函数中使用 Promise 和异步回调函数&#xff0c;比如网络资源获取&#xff0c;定时器设置等&#xff1b; 页面生命周期 即被Entry 装饰的组件生命周期&#xff0c;提供以下生命周期接口&#xff1a; onPageShow 页面加载时触发&#xff…

2023年上半年网络工程师真题(3/3)

41.某主机无法上网&#xff0c;查看本地连接后&#xff0c;发现只有发送包没有接收包&#xff0c;故障原因可能是&#xff08;C&#xff09;。 A.网线没有插好 B.DNS配置错误 C.IP地址配置错误 D.TCP/IP协议故障 如果网线没有插好&#xff0c;就没有发送包没有接收包;DNS配…

UI设计中的插画运用优势(上)

1. 插画是设计的原创性和艺术性的基础 无论是印刷品、品牌设计还是UI界面&#xff0c;更加风格化的插画能够将不同的风格和创意加入其中&#xff0c;在激烈的竞争中更容易因此脱颖而出。留下用户才有转化。 2. 插画是视觉触发器&#xff0c;瞬间传达大量信息 我们常说「一图胜千…

Skydel 23.8新版本发布!GNSS模拟器完成首项实地路测项目

奥本大学自动驾驶团队运用GNSS模拟器完成首项实地路测项目 奥本大学与最近与阿拉巴马州伯明翰的巴伯赛车运动公园合作进行道路测试&#xff0c;该车在没有任何人工干预的情况下成功绕赛道完成了一圈&#xff0c;这也是印地自动驾驶挑战赛中车辆首次在美国专业赛道上完成一圈。…