写在前边

链接:Educational Codeforces Round 103 (Rated for Div. 2)

A. K-divisible Sum

链接:A题链接

题目大意:

要求构造一个\(a\)数组使得\(a\)的和可以被\(k\)整除,在这个条件下让\(a\)中的最大值尽可能小。

思路

我是这样想的,就是n张牌组成\(k\),比如要求\(4\)张牌组成\(5, 6, 7, 8\)那么数组里最大的数最小肯定是\(2\),但是如果\(8 < k \leq 12\),那么就是\(3...\)了,而对于\(n < k\)的,我们想办法先让\(k > n\),然后再与上面同理,所以我是分类讨论的:

当\(n < k\)时,那么最大的那个数就是\(k / n\),如果无法整除则需要向上取整, 即\(k / n + (k \% n == 0 ? 0 : 1)\)。

当\(k = n\)时,那么最大的数最小肯定就是\(k / n = 1\)了。

当\(n > k\)时,那么我们可以先让\(k > n\),即\(k = k * (n / k + (n \% k == 0 ? 0 : 1))\),然后就与第一种情况同理了。

看到好多被\(hack\)的代码也是用这种思路,但是没有考虑无法整除向上取整的问题。

顺便新学了一招:\(q = \lceil \cfrac{n}{k} \rceil = \lfloor \cfrac{n + k - 1}{k} \rfloor\),这样向上取整就用不着再用三目运算符啦!

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <unordered_map> using namespace std; #define Inf 0x3f3f3f3f
#define PII pair<int, int>
#define P2LL pair<long long, long long> typedef long long LL;
typedef unsigned long long ULL;
typedef vector<long long> VLL;
typedef vector<int> VI; void solve() {
LL n, k;
cin >> n >> k;
if (n > k) {
LL t1 = n / k;
k = k * (t1 + (n % k == 0 ? 0 : 1));
LL t2 = k / n;
cout << t2 + (k % n == 0 ? 0 : 1) << '\n';
return;
} else if (k == n) {
cout << 1 << endl;
return;
} else {
LL t2 = k / n;
cout << t2 + (k % n == 0 ? 0 : 1) << '\n';
}
} int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--) {
solve();
} return 0;
}

B. Inflation

链接:B题链接

题目大意:

修改一个序列,让其通货膨胀系数不能超过\(k%\),输出序列修改了多少。

而\(p_i\)的通货膨胀系数:\(k_i = \cfrac{p_i}{p_1 + p_2 + ... + p_{i-1}}\),求出最小的修改数。

思路

看到这个题因为枚举到后边的时候我们只关心前缀和就可以,不用具体关心前边某一个元素该怎么变化,所以就想到了前缀和,但是还是因为浮点数问题,其实类似问题已经在\(atc\)中一场比赛意识到了,遇到除法能不用小数就不用,比如判断是否合理的时候可以转化成乘法判断\(a[i] * 100 <= s[i-1] * k\),最后终于修改的差不多了,还是有一个地方没有处理好,赛后才看到一个人代码恍然大悟,除不尽的时候应该向上取整的,可惜了。

向上取整还是用这种方法:\(q = \lceil \cfrac{n}{k} \rceil = \lfloor \cfrac{n + k - 1}{k} \rfloor\)

代码:

一开始的核心代码是这样的,用数组\(s\)来维护前缀和,但是每次都要再维护一下前缀和,明显增加了时间复杂度。

void deal(int k, LL temp) {
for (int i = k; i <= n; i++) {
s[i] += temp;
}
} void solve() {
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
s[i] = s[i - 1] + a[i];
}
LL sum = 0;
for (int i = 2; i <= n; i++) {
if (a[i] * 100 <= s[i-1] * k) {
continue;
} else {
LL temp = (a[i] * 100 - k * s[i-1]) / k;
temp = (a[i] * 100 - k * s[i-1]) % k == 0 ? temp : temp + 1;
sum += temp;
deal(i - 1, temp); //处理前缀和
}
} cout << sum << endl;
}

后来优化了很多,包括代码的长短,以及用一个变量来维护前缀和。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <unordered_map>
#include <cmath> using namespace std; #define Inf 0x3f3f3f3f
#define PII pair<int, int>
#define P2LL pair<long long, long long> typedef long long LL;
typedef unsigned long long ULL;
typedef vector<long long> VLL;
typedef vector<int> VI; const int N = 110;
LL a[N];
LL n, k; void solve() {
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
LL sum = 0, preSum = a[1];
for (int i = 2; i <= n; i++) {
if (a[i] * 100 > preSum * k) {
LL temp = (a[i] * 100 - k * preSum + k - 1) / k;
sum += temp;
preSum += temp;
}
preSum += a[i];
} cout << sum << endl;
} int main()
{
//ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--) {
solve();
} return 0;
}

C. Longest Simple Cycle

链接:C题链接

题目大意:

不描述原题了,有点难描述。。

思路

因为我们求得一个圈的长度,而一个圈的右边必然右一条链组成,所以我们从第二条链往后枚举每一条链,对于每一个圈的右半部分长度就是\(c[i] + 1\),而对于左半部分,如果\(a_i == b_i\)那么就说明右半部分重合到一点了,否则就是\(abs(a_i - b_i)\),维护一个\(curlen\)以及一个\(lastlen\),对于\(a_i != b_i\)的时候,我们可以判断一下左边的环与右边的环接起来是否会更大,如果更大就把中间的\(abs(a_i - b_i)\)去掉,即\(curlen = max(curlen, c[i] + 1 + lastlen - abs(a[i] - b[i]))\),然后更新\(res\)以及\(lastlen\)即可

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <unordered_map> using namespace std; #define Inf 0x3f3f3f3f
#define PII pair<int, int>
#define P2LL pair<long long, long long> typedef long long LL;
typedef unsigned long long ULL;
typedef vector<long long> VLL;
typedef vector<int> VI; const int N = 2e5 + 10;
LL c[N], a[N], b[N]; void solve() {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> c[i];
}
for (int i = 0; i < n; i++) {
cin >> a[i];
}
for (int i = 0; i < n; i++) {
cin >> b[i];
}
LL res = 0, curlen = 0, lastlen = 0;
for (int i = 1; i < n; i++) {
curlen = c[i] + 1 + abs(a[i] - b[i]);
if (a[i] != b[i]) {
curlen = max(curlen, c[i] + 1 + lastlen - abs(a[i] - b[i]));
}
res = max(res, curlen);
lastlen = curlen;
}
cout << res << endl;
} int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--) {
solve();
} return 0;
}

D. Journey

链接:D题链接

题目大意:

给定一组\(n\)个道路的方向,链接了\(n + 1\)个城市,旅游时只能按照道路方向旅游,同时走一次道路那么所有的道路就反向一次,比如原来道路方向只能是\(A->B\),但是到\(B\)之后道路会反向,所以然后还可以从\(B\)返回\(A\),求从每一个城市可以旅行到的最多城市。

思路

一种是利用本题的性质,因为去还可以回来,所以可以说是一种无向边,但是并查集(\(DSU\)),\(BFS\),\(DFS\)代码我看了一上午,实在看不懂,想不明白。

于是用递推的方式做了,即用\(dpl_i\)表示\(i\)城市从\(i\)城市向左可以最多走到的城市标号,用\(dpr_i\)表示从\(i\)城市向右可以最多走到的城市标号,最后答案就是\(num_i = dpr_i -dpl_i +1\),只不过要注意的细节比较多。

对于\(dpl_i\):

  1. 如果不能向左走,那么:\(dpl_i = i\)。
  2. 如果能向左走一步那么:\(dpl_i = i-1\)
  3. 然后就可以直接转移了:\(dpl_i = dpl_{i-2}\)

    对于\(dpr_i\)同理,从后向前递推即可。

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector> using namespace std; #define Inf 0x3f3f3f3f
#define PII pair<int, int>
#define P2LL pair<long long, long long>
#define endl '\n' typedef long long LL;
typedef unsigned long long ULL;
typedef vector<long long> VLL;
typedef vector<int> VI; const int N = 3E5 + 10;
char s[N];
int n;
int dpl[N], dpr[N]; void solve() {
scanf("%d", &n);
scanf("%s", s + 1);
for (int i = 1; i <= n + 1; i++) {
dpl[i] = i;
}
for (int i = 1; i <= n + 1; i++) {
dpr[i] = i;
}
for (int i = 1; i <= n + 1; i++) {
if (i == 1 || s[i - 1] == 'R') { //向左走不动
dpl[i] = i;
} else if (i == 2 || s[i - 2] == 'L') { //向左只能走一格
dpl[i] = i - 1;
} else {
dpl[i] = dpl[i - 2];
}
}
for (int i = n + 1; i >= 1; i--) {
if (i == n + 1 || s[i] == 'L') {
dpr[i] = i;
} else if (i == n || s[i + 1] == 'R') {
dpr[i] = i + 1;
} else {
dpr[i] = dpr[i + 2];
}
}
for (int i = 1; i <= n + 1; i++) {
printf("%d ", dpr[i] - dpl[i] + 1);
}
puts("");
} int main()
{
//ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int t;
scanf("%d", &t);
while (t--) {
solve();
} return 0;
}

Educational Codeforces Round 103 (Rated for Div. 2) A~D题解的更多相关文章

  1. Educational Codeforces Round 61 (Rated for Div. 2) D,F题解

    D. Stressful Training 题目链接:https://codeforces.com/contest/1132/problem/D 题意: 有n台电脑,每台电脑都有初始电量ai,也有一个 ...

  2. Educational Codeforces Round 81 (Rated for Div. 2) A-E简要题解

    链接:https://codeforces.com/contest/1295 A. Display The Number 贪心思路,尽可能放置更多位,如果n为奇数,消耗3去放置一个7,剩下的放1 AC ...

  3. Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship Time Limit: 2000 mSec P ...

  4. Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems(动态规划+矩阵快速幂)

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems Time Limit: 3000 mSec P ...

  5. Educational Codeforces Round 43 (Rated for Div. 2)

    Educational Codeforces Round 43 (Rated for Div. 2) https://codeforces.com/contest/976 A #include< ...

  6. Educational Codeforces Round 35 (Rated for Div. 2)

    Educational Codeforces Round 35 (Rated for Div. 2) https://codeforces.com/contest/911 A 模拟 #include& ...

  7. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings 题目连接: http://cod ...

  8. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes 题目连接: http://code ...

  9. Educational Codeforces Round 63 (Rated for Div. 2) 题解

    Educational Codeforces Round 63 (Rated for Div. 2)题解 题目链接 A. Reverse a Substring 给出一个字符串,现在可以对这个字符串进 ...

  10. Educational Codeforces Round 39 (Rated for Div. 2) G

    Educational Codeforces Round 39 (Rated for Div. 2) G 题意: 给一个序列\(a_i(1 <= a_i <= 10^{9}),2 < ...

随机推荐

  1. return true 与 return false的妙用——jQuery

    var arr = [1, 3, 5,7,9]; jQuery.each(arr, function(key, value){ if(key === 2){ return true; } consol ...

  2. 常见的 NoSQL 数据库有哪些?

    前言 今天我们来介绍一下工作开发中常见的一些NoSQL数据库及其基本特点.欢迎在评论区留下文章中没有介绍且好用的​NOSQL数据库. 什么是NOSQL数据库 非关系型数据库又被称为 NoSQL(Not ...

  3. tcp3次握手

    tcp3次握手 1,三次握手流程图 2,三握手过程 当pc1想和pc2建立起连接时 pc1将连接信息写入报文 2.1,报文的序号(seq=x) 同步位(请求建立连接关系: SYN=1 ACK=0 控制 ...

  4. BurpSuite设置上游代理访问内网

    转载原文 原理知道了后,开始! 拿到B的shell后,添加路由 拿到B的shell后,开启sock4 在D主机上设置好 最后成功抓到包

  5. Unity的IPreprocessComputeShaders:深入解析与实用案例

    Unity IPreprocessComputeShaders Unity IPreprocessComputeShaders是Unity引擎中的一个非常有用的功能,它可以让开发者编译Compute ...

  6. idea的maven home默认路径无法修改成功的问题

    主要原因是项目里有许多初始默认文件 删除项目初始化后的生成的.mvn mvnw mvnw.cmd help.md .gitignore等文件后再修改mavenhome,然后reload maven就修 ...

  7. ThreadLocal的学习心得

    ThreadLocal是Java提供的线程本地存储机制,可以实现多线程环境下数据的隔离.主要特点是: 每个线程都有自己的实例副本,实现了线程的数据隔离.ThreadLocal中存储的值对其他线程都不可 ...

  8. 《SQL与数据库基础》08. 多表查询

    目录 多表查询 多表关系 一对多 多对多 一对一 多表查询概述 分类 内连接 外连接 自连接 联合查询 子查询 分类 标量子查询 列子查询 行子查询 表子查询 案例 本文以 MySQL 为例 多表查询 ...

  9. 2023-09-03:用go编写。给你一个 n 个节点的无向无根树,节点编号从 0 到 n - 1 给你整数 n 和一个长度为 n - 1 的二维整数数组 edges , 其中 edges[i] =

    2023-09-03:用go语言编写.给你一个 n 个节点的无向无根树,节点编号从 0 到 n - 1 给你整数 n 和一个长度为 n - 1 的二维整数数组 edges , 其中 edges[i] ...

  10. RocketMQ 系列(四) 消息存储

    RocketMQ 系列(四) 消息存储 本文是 RocketMQ 系列的第四篇,下面是前面几篇的文章,不清楚的话点击看一下吧. RocketMQ系列(一) 基本介绍 RocketMQ 系列(二) 环境 ...