Codeforces Round 942 (Div.1) (Div. 2) 2A~2D

2024-05-08 22:36
文章标签 codeforces round div 2d 2a div.1 942

本文主要是介绍Codeforces Round 942 (Div.1) (Div. 2) 2A~2D,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2A.Contest Proposal(枚举)

题意:

一个竞赛包含 n n n个问题,第 i i i个问题的难度预计最多 b i b_i bi。现在已经有 n n n个问题提案,第 i i i个问题的难度为 a i a_i ai。最初, a 1 , a 2 , … , a n a_1,a_2,\ldots,a_n a1,a2,,an b 1 , b 2 , … , b n b_1,b_2,\ldots,b_n b1,b2,,bn都是按非递减顺序排序的。

有些问题可能比预期的更难,因此作者必须提出更多的问题。当提出难度为 w w w的新问题时,最难的问题将从竞赛中删除,问题将以难度不递减的方式排序。

换句话说,在每次操作中,你都要选择一个整数 w w w,将其插入数组 a a a中,对数组 a a a进行非递减排序,并从中删除最后一个元素。

求使对于所有 i i i都有 a i ≤ b i a_i\le b_i aibi的的最小新问题数。

分析:

因为选的 w w w一定可以让它合法,一次操作可以看作 a a a数组向右平移一位。遍历 a a a数组中每个数和第一个比 b b b数组小的差值,取最大值即可。

代码:

#include<bits/stdc++.h>typedef long long LL;
using namespace std;
const LL N = 105;
LL a[N], b[N];int main() {int t;cin >> t;while (t--) {int n, ans = 0, flag = 0;cin >> n;for (int i = 0; i < n; i++) {cin >> a[i];}for (int i = 0; i < n; i++) {cin >> b[i];}for (int i = 0; i < n; i++) {flag = 0;for (int j = i; j < n; j++) {if (a[i] <= b[j]) {ans = max(j - i, ans);flag = 1;j = n;}}if (flag == 0) {ans = max(n - i, ans);}}cout << ans << endl;}return 0;
}

2B.Coin Games(博弈)

题意:

桌子上有 n n n枚硬币围成一个圆圈,每枚硬币要么朝上,要么朝下。爱丽丝和鲍勃轮流玩下面的游戏,爱丽丝先玩。

在每次操作中,玩家选择一枚正面朝上的硬币,取出硬币并翻转与其相邻的两枚硬币。如果(操作前)只剩下两枚硬币,则取出一枚,另一枚不翻转(因为会翻转两次)。如果(操作前)只剩下一枚硬币,则不会翻转任何硬币。如果(操作前)没有正面朝上的硬币,玩家就输了。

如果两人都以最佳方式下棋,谁会赢呢?可以证明,游戏将在有限次的操作中结束,其中一人将获胜。

分析:

U U U视作 1 1 1,将 D D D视作 0 0 0,一次操作就是拿走一个 1 1 1,将两侧分别异或 1 1 1

观察样例,猜测 U U U有奇数个先手赢,反之后手赢。

证明:根据上述转化,判定条件等价于判断全局异或和为 0 0 0还是为 1 1 1。一次操作对全局异或和的影响是将其与 1 1 1进行异或。

初始异或和为 1 1 1时,先手必定可以操作,到后手时异或和为 0 0 0,后手可能可以操作,回到先手,异或和还是 1 1 1,必定可以操作。如此往复,只要后手能操作,先手必定可以操作。

另一种情况类似。

代码:

#include<bits/stdc++.h>using namespace std;void solve() {int n;cin >> n;string s;cin >> s;int cnt = 0;for (int i = 0; i < n; i++)if (s[i] == 'U')++cnt;if (!cnt) {cout << "NO" << endl;return;}if (cnt & 1) {cout << "YES" << endl;} else {cout << "NO" << endl;}
}int main() {int t;cin >> t;while (t--) {solve();}return 0;
}

2C1A.Permutation Counting(贪心)

题意:

你有一些卡片。每张卡片上都写着一个介于 1 1 1 n n n之间的整数:具体来说,从 1 1 1 n n n的每张 i i i,你们有 a i a_i ai张卡片,上面写着数字 i i i

还有一个商店,里面有无限量的各种类型的卡片。你有 k k k枚金币,因此你总共可以购买 k k k张新卡片,你所购买的卡片可以包含 1 1 1 n n n之间的任意整数。

购买新牌后,您要将所有牌重新排列成一行。重新排列的得分是长度为 n n n的(连续)子数组中 [ 1 , 2 , … , n ] [1,2,\ldots,n] [1,2,,n]的排列数。你能得到的最高分是多少?

分析:

贪心地考虑优先用 k k k买原本数量少的卡片,使每种卡片的最少数量尽可能大。

推导一下可以发现使答案尽可能大的结构是 1 , 2 , 3 , 4 , 1 , 2 , 3 , 4 1,2,3,4,1,2,3,4 1,2,3,4,1,2,3,4这样的排列。

计算贡献,假设最小值为 x x x,比 x x x大的有 y y y个,我们一定会把这 y y y个尽量往前放,让较小的 x x x利用充分,这样总共有 ( x − 1 ) n + 1 + y (x−1)n+1+y (x1)n+1+y个合法子段。

然后就是模拟,把 k k k尽量往数量少的分。使用差分维护即可。

代码:

#include<bits/stdc++.h>typedef long long LL;
using namespace std;void solve() {LL n, k;cin >> n >> k;vector<LL> a(n, 0);for (int i = 0; i < n; i++)cin >> a[i];sort(a.begin(), a.end());vector<LL> dlt(n, 0);for (LL i = 0; i < n - 1; i++) {if (!k)break;LL x = (i + 1) * (a[i + 1] - a[i]);if (k >= x) {dlt[i] += a[i + 1] - a[i];k -= x;} else {LL d = k / (LL) (i + 1);for (LL j = 0; j <= i; j++)a[j] += d;k -= (i + 1) * d;for (LL j = i; j >= 0; j--)if (k) {++a[j];--k;}break;}}LL sum = 0;for (LL i = n - 1; i >= 0; i--)sum += dlt[i], a[i] += sum;LL d = k / (LL) n;k -= n * d;for (LL i = n - 1; i >= 0; i--)a[i] += d;for (LL i = n - 1; i >= 0; i--)if (k) {++a[i];--k;}LL res = 0;for (LL i = n - 1; i >= 0; i--)if (a[i] > a[0])++res;cout << a[0] * n - n + 1 + res << endl;
}int main() {int t;cin >> t;while (t--)solve();return 0;
}

2D1(1B1).Reverse Card (Easy Version)(数学)

题意:

给你两个正整数 n n n, m m m

请计算满足以下条件的有序数对 ( a , b ) (a,b) (a,b)的个数:

  • 1 ≤ a ≤ n 1\le a\le n 1an, 1 ≤ b ≤ m 1\le b\le m 1bm;
  • a + b a+b a+b b ⋅ gcd ⁡ ( a , b ) b\cdot\gcd(a,b) bgcd(a,b)的倍数。

分析:

g c d ( a , b ) gcd(a,b) gcd(a,b)一定是等于 b b b,问题转换为 ( a + b ) % ( b ∗ b ) = = 0 (a+b)\%(b*b)==0 (a+b)%(bb)==0

那么 a a a b b b的倍数一定成立,可以通过枚举 b b b来找 a a a

代码:

#include<bits/stdc++.h>using namespace std;void solve() {int n, m;cin >> n >> m;int ans = 0;for (int b = 1; b <= m; ++b) {ans += (n / b + 1) / b - (b == 1);}cout << ans << endl;
}int main() {int t;cin >> t;while (t--)solve();return 0;
}

2D2(1B2).Reverse Card (Hard Version)(数学)

题意:

给你两个正整数 n n n, m m m

请计算满足以下条件的有序数对 ( a , b ) (a,b) (a,b)的个数:

  • 1 ≤ a ≤ n 1\le a\le n 1an, 1 ≤ b ≤ m 1\le b\le m 1bm;
  • b ⋅ gcd ⁡ ( a , b ) b\cdot\gcd(a,b) bgcd(a,b) a + b a+b a+b的倍数。

分析:

gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b)表示为 d d d。假设有 a = p d a=pd a=pd b = q d b=qd b=qd,那么我们知道 gcd ⁡ ( p , q ) = 1 \gcd(p,q)=1 gcd(p,q)=1.

( a + b ) ∣ ( b ⋅ gcd ⁡ ( a , b ) ) ⟺ ( p d + q d ) ∣ ( q d 2 ) ⟺ ( p + q ) ∣ ( q d ) (a+b)\mid(b\cdot\gcd(a,b))\iff(pd+qd)\mid(qd^2)\iff(p+q)\mid (qd) (a+b)(bgcd(a,b))(pd+qd)(qd2)(p+q)(qd)

已知 gcd ⁡ ( p + q , q ) = gcd ⁡ ( p , q ) = 1 \gcd(p+q,q)=\gcd(p,q)=1 gcd(p+q,q)=gcd(p,q)=1,所以是 ( p + q ) ∣ d (p+q)\mid d (p+q)d

我们还知道 p ≥ 1 , q ≥ 1 p\ge 1,q\ge 1 p1,q1,所以 p < d = a p ≤ n p p\lt d=\frac{a}{p}\le\frac{n}{p} p<d=papn,从而 p 2 < n p^2\lt n p2<n。同样,我们可以证明 q 2 < m q^2\lt m q2<m

所以 ( p , q ) (p,q) (p,q)的个数是 O ( n m ) = O ( n + m ) \mathcal O(\sqrt{nm})=\mathcal O(n+m) O(nm )=O(n+m)。我们可以枚举出 gcd ⁡ ( p , q ) = 1 \gcd(p,q)=1 gcd(p,q)=1的每个 ( p , q ) (p,q) (p,q),并计算出答案。需要 ( p + q ) ∣ d (p+q)\mid d (p+q)d,因此我们加上 ⌊ min ⁡ { ⌊ n p ⌋ , ⌊ m q ⌋ } p + q ⌋ \left\lfloor\frac{\min\{\lfloor\frac{n}{p}\rfloor,\lfloor\frac{m}{q}\rfloor\}}{p+q}\right\rfloor p+qmin{⌊pn,qm⌋}

时间复杂度: O ( ∑ n + ∑ m ) \mathcal O(\sum n+\sum m) O(n+m)

代码:

#include <bits/stdc++.h>using namespace std;typedef long long ll;int main() {int t;cin >> t;while (t--) {ll n, m;cin >> n >> m;ll sq = sqrt(n) + 2, sqm = sqrt(m) + 2;vector bad(sq + 1, vector<bool>(sqm + 1, 0));for (ll i = 2; i <= min(sq, sqm); i++) {for (ll a = i; a <= sq; a += i) {for (ll b = i; b <= sqm; b += i) {bad[a][b] = true;}}}ll ans = 0;for (ll a = 1; a * a <= n; a++) {for (ll b = 1; b * b <= m; b++) {if (bad[a][b]) continue;ans += min(n / (a + b) / a, m / (a + b) / b);}}cout << ans << endl;}return 0;
}

赛后交流

在比赛结束后,会在交流群中给出比赛题解,同学们可以在赛后查看题解进行补题。

群号: 704572101,赛后大家可以一起交流做题思路,分享做题技巧,欢迎大家的加入。

这篇关于Codeforces Round 942 (Div.1) (Div. 2) 2A~2D的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/971625

相关文章

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

Codeforces Round #261 (Div. 2)小记

A  XX注意最后输出满足条件,我也不知道为什么写的这么长。 #define X first#define Y secondvector<pair<int , int> > a ;int can(pair<int , int> c){return -1000 <= c.X && c.X <= 1000&& -1000 <= c.Y && c.Y <= 1000 ;}int m

Codeforces Beta Round #47 C凸包 (最终写法)

题意慢慢看。 typedef long long LL ;int cmp(double x){if(fabs(x) < 1e-8) return 0 ;return x > 0 ? 1 : -1 ;}struct point{double x , y ;point(){}point(double _x , double _y):x(_x) , y(_y){}point op

Codeforces Round #113 (Div. 2) B 判断多边形是否在凸包内

题目点击打开链接 凸多边形A, 多边形B, 判断B是否严格在A内。  注意AB有重点 。  将A,B上的点合在一起求凸包,如果凸包上的点是B的某个点,则B肯定不在A内。 或者说B上的某点在凸包的边上则也说明B不严格在A里面。 这个处理有个巧妙的方法,只需在求凸包的时候, <=  改成< 也就是说凸包一条边上的所有点都重复点都记录在凸包里面了。 另外不能去重点。 int

Codeforces 482B 线段树

求是否存在这样的n个数; m次操作,每次操作就是三个数 l ,r,val          a[l] & a[l+1] &......&a[r] = val 就是区间l---r上的与的值为val 。 也就是意味着区间[L , R] 每个数要执行 | val 操作  最后判断  a[l] & a[l+1] &......&a[r] 是否= val import ja

CSS实现DIV三角形

本文内容收集来自网络 #triangle-up {width: 0;height: 0;border-left: 50px solid transparent;border-right: 50px solid transparent;border-bottom: 100px solid red;} #triangle-down {width: 0;height: 0;bor

Matter.js:Web开发者的2D物理引擎

Matter.js:Web开发者的2D物理引擎 前言 在现代网页开发中,交互性和动态效果是提升用户体验的关键因素。 Matter.js,一个专为网页设计的2D物理引擎,为开发者提供了一种简单而强大的方式,来实现复杂的物理交互效果。 无论是模拟重力、碰撞还是复杂的物体运动,Matter.js 都能轻松应对。 本文将带你深入了解 Matter.js ,并提供实际的代码示例,让你一窥其强大功能

创建一个大的DIV,里面的包含两个DIV是可以自由移动

创建一个大的DIV,里面的包含两个DIV是可以自由移动 <body>         <div style="position: relative; background:#DDF8CF;line-height: 50px"> <div style="text-align: center; width: 100%;padding-top: 0px;"><h3>定&nbsp;位&nbsp;

Codeforces Round 971 (Div. 4) (A~G1)

A、B题太简单,不做解释 C 对于 x y 两个方向,每一个方向至少需要 x / k 向上取整的步数,取最大值。 由于 x 方向先移动,假如 x 方向需要的步数多于 y 方向的步数,那么最后 y 方向的那一步就不需要了,答案减 1 代码 #include <iostream>#include <algorithm>#include <vector>#include <string>

Unity3D在2D游戏中获取触屏物体的方法

我们的需求是: 假如屏幕中一个棋盘,每个棋子是button构成的,我们希望手指或者鼠标在哪里,就显示那个位置的button信息。 网上有很多获取触屏物体信息的信息的方法如下面代码所示: Camera cam = Camera.main; // pre-defined...if (touch.phase == TouchPhase.Bagan)){ // 如果触控点状态为按下Ray