Educational Codeforces Round 173 (Rated for Div. 2)题解(A-E)

news/2024/12/28 6:01:41/文章来源:https://www.cnblogs.com/autumnmist/p/18637012

Educational Codeforces Round 173 (Rated for Div. 2)题解(A-E)

A. Coin Transformation

你有一个价值为n的硬币,每次操作,如果n大于3,可以把硬币拆成两个价值为n/4的硬币
执行任意多次后,至多可以获得多少硬币?

显然,这是一个类似快速幂的行为

using i64 = long long;
void solve() {i64 n; cin >> n;i64 ans = 1;while (n > 3) {ans *= 2;n /= 4;}cout << ans << endl;
}

复杂度\(O(log_4n)\)

B. Digits

给定\(n,(2<=n<=10^9),d,(1<=d<=9)\),问如果\(n!\)个d串起来形成的数字,可以被[1,3,5,7,9]里哪些数整除?
比如n=3,d=2,则串起来是222222

观察题。分类讨论,设串起来的数字是S
1 必然是可以整除的
3 如果d%3=0或者n>=3则可以整除,d%3=0是显然的;如果n>=3,则S长度是3!的倍数,显然可以被3整除。
5 要想末尾是5或者0,只能d=5
7 d=7是一种情况,另外打表可知3!=111111%7=0,而对于n>3,则S长度是3!的倍数,则有\(S=(1+10^6+10^{12}+...)*111111\),显然可以整除7
9 类似3,更细节一点,d%9=0,或者d%3=0但是n>=3,或者n>=6(注意此时S长度是9的倍数)

using i64 = long long;
void solve() {i64 n, d; cin >> n >> d;vector<int> ans;ans.push_back(1);if (d % 3 == 0 || n >= 3) ans.push_back(3);if (d % 5 == 0) ans.push_back(5);if (d % 7 == 0 || n >= 3) ans.push_back(7);if (d % 9 == 0 || d % 3 == 0 && n >= 3 || n >= 6) ans.push_back(9);for (auto v : ans) cout << v << " ";cout << endl;
}

复杂度\(O(1)\)

C. Sums on Segments

一个数组,元素均为-1或者1,但是至多可能存在一个元素是\(-10^9\sim10^9\)
顺序排列所有子数组的和(去重)

假设没有这个额外的元素,很容易意识到这是求最大/最小子数组和,由于数字绝对值为1,所以[min,max]之间必然全部出现,顺序打印即可。
简述下如何求最大子数组和

int ans = 0, sum = 0; //本题可以为空,否则ans应以INT_MIN为初值。
for (auto v : nums) {sum += v;ans = max(ans , sum);if(sum < 0) sum = 0;
}

但是数组中可能存在一个非{-1,1}的元素x,如何处理?
答案由两部分构成,一部分是不包含x,即左右两侧的子数组和的并集。
\([min(leftMin, rightMin), max(leftMax, rightMax)]\)
另一部分是包含x,小心,包含x的话,必须是整体连续
即左部分+x+右部分是连续的。
左部分是以[x-1]为右端点的子数组值域范围
右部分是以[x+1]为左端点的子数组值域范围
注意两部分合并是\([leftMin+rightMin, leftMax+rightMax]\),再加上x即可
题目不难,写起来麻烦

using i64 = long long;
void solve() {int n; cin >> n;vector<int> nums(n);int x = 0; //如果没有找到非{-1,1}的元素,那就取第一个元素即可。for (int i = 0; i < n; i++) {cin >> nums[i];if (nums[i] != 1 && nums[i] != -1) x = i;}//计算[L,R]的子数组最大值和最小值auto dfs = [&](int L, int R, bool calcMin = true)->int {int res = 0, sum = 0;for (int i = L; i <= R; i++) {int v = nums[i];sum += v;res = calcMin ? min(res, sum) : max(res, sum);if (calcMin && sum > 0) sum = 0;if (!calcMin && sum < 0) sum = 0;}return res;};int minSum = min(dfs(0, x - 1, true), dfs(x + 1, n - 1, true));int maxSum = max(dfs(0, x - 1, false), dfs(x + 1, n - 1, false));set<int> set;for (int i = minSum; i <= maxSum; i++) set.insert(i);//不包含x的部分//以下标x-1为右端点的子数组范围int leftMin = 0, leftMax = 0, leftSum = 0;for (int i = x - 1; i >= 0; i--) {leftSum += nums[i];leftMin = min(leftMin, leftSum);leftMax = max(leftMax, leftSum);}//以下标x+1为左端点的子数组范围int rightMin = 0, rightMax = 0, rightSum = 0;for (int i = x + 1; i < n; i++) {rightSum += nums[i];rightMin = min(rightMin, rightSum);rightMax = max(rightMax, rightSum);}minSum = leftMin + rightMin + nums[x];maxSum = leftMax + rightMax + nums[x];for (int i = minSum; i <= maxSum; i++) set.insert(i);//包含x的部分cout << set.size() << endl;for (auto v : set) {cout << v << " ";}cout << endl;
}

复杂度最优可以是\(O(n)\),两个区间最后求并集即可。
这里为了方便,直接使用了set去重和排序,此时复杂度是\(O(nlogn)\)

D. Problem about GCD

已知区间L,R,和一个整数G,\(0<L,R,G<10^{18}\)
求整数对A B,要求\(L<=A<=B<=R\),且GCD(A,B)=G,且要最大化B-A。

最关键的点在于GCD(A,B)=G的意义,这表示A,B都是G的倍数,且\(\frac{A}{G}\)\(\frac{B}{G}\)互质。
然后就是,给定两个数P,Q,要想保证区间[P, P+d]和区间[Q,Q+d]中存在互质数对,d的取值可以很小...
证明是不会证明的,反正暴力过了...我才不会说取值从1000降到100又降到30才过的...

using i64 = long long;
i64 gcd(i64 a, i64 b) { return b == 0 ? a : gcd(b, a % b); }
void solve() {i64 L, R, G; cin >> L >> R >> G;i64 mL = (L + G - 1) / G; //mL*G是[L,R]中G的倍数最小值i64 mR = R / G; //mR*G是[L,R]中G的倍数最大值i64 r1 = -1, r2 = -1;i64 mx = -1;for (i64 i = mL; i <= mR && i < mL + 30; i++) {for (i64 j = mR; j >= mR - 30 && j >= i; j--) {if (gcd(i, j) == 1) {if (j - i > mx) {r1 = i * G;r2 = j * G;mx = j - i;}}}}cout << r1 << " " << r2 << endl;
}

复杂度不确定,就记作\(O(C^2logU)\)吧,其中\(C<30\)

E. Matrix Transformation

给定矩阵A,B 定义两种操作
任选矩阵A一行\(i\),任选\(x>=0\),对这一行所有元素执行\(A_{ij} = A_{ij}\&x\)
任选矩阵A一列\(j\),任选\(x>=0\),对这一列所有元素执行\(A_{ji} = A_{ji}|x\)
问,能否将A转换为B

很好的题。
首先要能意识到拆位操作,因为可以选择x=1<<k,则不同bit之间是操作无关的。
问题转换为A,B均为0 1矩阵。
举一个最简明的例子

\[\begin{flalign} A=\begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix} ,B=\begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}&& \end{flalign} \]

A左下角的1,必须通过行变换为0,才能与B一致
然后A右下角再执行列变换为1
然后A右上角再执行行变换为0
最后当A左上角执行列变换为1时,此时左下角从0变回了1。
产生了循环,所以A是无法变成B的。
这启发我们,行列的变换不能产生环。
具体的:

  • 我们先枚举所有位置,如果\(A_{ij}\)\(B_{ij}\)不相等,则必须产生一次变换。
    如果\(B_{ij}\)为0,则是行变换,否则是列变换。
  • 一轮枚举结束后,我们考虑某一变换的行或列,以行为例,该行的每个元素变换后都会变成0
    那么我们需要检查B的对应行是否全为0, 有不是0的,则需要对该列执行列变换。
  • 如果有新的变换添加进来,则需要重复执行上述检查操作,直到无新增变换为止。
  • 此时按照所有产生操作的的行和列,和对应的\(B_{ij}\)的值,进行连边处理。
    如果\(B_{i,j}=1\),则\(i\)行需要向\(j\)列连边,表示需要先执行行变换,再执行列变换。
    反之从\(j\)列向\(i\)行连边。
  • 最后就是简单的有向图判环。这可以用dfs染色,拓扑排序,并查集等手段处理。

以下是完整代码。

#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
void solve()
{int n, m; cin >> n >> m;vector<vector<int>> A(n), B(n);for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {int v; cin >> v;A[i].push_back(v);}}for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {int v; cin >> v;B[i].push_back(v);}}//拆位处理for (int k = 0; k <= 30; k++) {//第一轮枚举 将变化的行列加入队列中。queue<int> q;vector<int> flagX(n), flagY(m);for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (!flagX[i] && (A[i][j] >> k & 1) && !(B[i][j] >> k & 1)) {flagX[i] = 1;q.push(i);}if (!flagY[j] && !(A[i][j] >> k & 1) && (B[i][j] >> k & 1)) {flagY[j] = 1;q.push(n + j);}}}//循环检测是否有新变换加入,直到无新增为止while (!q.empty()) {int u = q.front();q.pop();if (u < n) {for (int j = 0; j < m; j++) {if (!flagY[j] && (B[u][j] >> k & 1)) {flagY[j] = true;q.push(j + n);}}}else {for (int i = 0; i < n; i++) {if (!flagX[i] && !(B[i][u - n] >> k & 1)) {flagX[i] = true;q.push(i);}}}}//有向图建立vector<vector<int>> g(n + m);vector<int> deg(n + m);for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (flagX[i] && !(B[i][j] >> k & 1)) {deg[j + n]++;g[i].push_back(j + n);}if (flagY[j] && (B[i][j] >> k & 1)) {deg[i]++;g[j + n].push_back(i);}}}//以下是拓扑排序求环int count = n + m;queue<int> que;for (int i = 0; i < n; i++) if (deg[i] == 0) que.push(i);for (int j = 0; j < m; j++) if (deg[j + n] == 0) que.push(j + n);while (!que.empty()) {int u = que.front();que.pop();count--;for (auto v : g[u]) {deg[v]--;if (deg[v] == 0) que.push(v);}}//只要有某一位不合法返回NOif (count) {cout << "NO" << endl;return;}}cout << "YES" << endl;
}
int main() {std::ios::sync_with_stdio(false);cin.tie(nullptr);int t = 1; cin >> t;while (t-- > 0) {solve();}
}

复杂度为\(O(nmlogU)\)

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

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

相关文章

SPIR-V的开源编译器生态系统API分层

API分层 SPIR-V的开源编译器生态系统越来越强大。 1.行分层 无需额外的内核级驱动程序即可实现内容,从而使平台受益。 OpenCL接口分层,如图1-30所示。图1-30 OpenCL接口分层 2.列分层 即使没有本机驱动程序,也可以跨多个平台提供API,以便提供应用程序部署灵活性并消除碎片,…

分层OpenCL实现

分层OpenCL实现 OpenCL接口分层实现,如图1-31所示。图1-31 OpenCL接口分层实现人工智能芯片与自动驾驶

《智能汽车传感器:原理设计应用》《AI芯片开发核心技术详解》新书推荐

两本书推荐《AI芯片开发核心技术详解》、《智能汽车传感器:原理设计应用》由清华大学出版社资深编辑赵佳霓老师策划编辑的新书《AI芯片开发核心技术详解》已经出版,京东、淘宝天猫、当当等网上,相应陆陆续续可以购买。该书强力解析AI芯片的核心技术开发,内容翔实、知识点新…

Excel+Python 飞速搞定数据分析与处理(图灵出品)PDF免费下载

零基础Python编程数据分析,Excel办公自动化处理,告别烦琐公式,办公人士也能轻松学习Python数据处理自动化,让你的Excel快得飞起来!适读人群 :本书既适合Excel用户,也适合Python用户阅读。电子版仅供预览,下载后24小时内务必删除,支持正版,喜欢的请购买正版书籍:http…

移动端滑动,better-scroll使用

背景 为博客园做移动端适配,有一个控件需要固定大小,但是里面的内容是动态的,很有可能放不下,因此需要滑动。 设置了滑动后,我发现划不动,原来原生的滑动是不管你什么移动端的,于是找移动端适配的滑动。 Better-Scroll 名声很大,坑不少。 划不动 官方文档写的快速开始实…

JAVA-第三次大作业blog

一.前言 在深入探索Java编程的征途中,我迎来了第七、八次PTA题目集的挑战。这两次作业不仅是对我学习成果的检验,更是深化我对Java核心概念——继承理解的宝贵契机。通过亲身实践,我不仅巩固了继承在Java中的应用技巧,还跨越性地深化了对子类与父类关系的洞察。每一次编码,…

Unity音频管理方案

AudioManager类的创建可以序列化,就可以在外面看到然后在Awake里面初始化一下AudioManager类的完善 写个单例:这样就可以直接在外面AudioManager.去调用比较方便 使用AudioMixer对音频进行分组使用unity自带的AudioMixer使用unity自带的AudioMixer进行音量统一处理在UI框架里…

没有xml configuration file

点击new菜单发现没有看到XML Configuration File选项。1、正确导入spring jar包,spring5.6 maven坐标<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>6.2.1</versi…

PostgreSQL 数据库的启动与停止管理

title: PostgreSQL 数据库的启动与停止管理 date: 2024/12/28 updated: 2024/12/28 author: cmdragon excerpt: 作为一个强大的开源关系数据库管理系统,PostgreSQL在众多应用场景中发挥着关键作用。在实际使用过程中,对于数据库的启动和停止操作至关重要。这不仅关系到数据…

人工智能Agent提示工程的六个关键要素

一个构造良好的提示封装了所有必要的信息,确保AI Agent生成准确的响应并有效地执行任务。 通过系统地组合特定组件,提示符为LLM提供了一个全面的框架,以实现最佳功能。 六个关键要素如下: 1.用户请求:这是用户提供的原始任务描述,概述了目标和期望的结果。它作为代理行为…

一个Java实现的OCR系统

一个Java实现的OCR系统 利用java17实现的一套OCR推理系统,兼容paddleocr。如下图,目前功能如下,https://github.com/jiangnanboy/JiaJiaOCR:

staticfile cdn崩了,boot cdn崩了。

背景 一天之内碰到两个cdn同时炸。 staticfile cdnboot cdn我没截图,他主站是没炸的,但是js文件访问不了,过了一段时间又好了。 后面恢复了,下面是bootcdn的速度测试,有点慢说实话。其他bootcdn太慢了,换一家用用。npmmirror 全国最nb的镜像站,无需多言。 格式如下 http…