Codeforces Round 911 (Div. 2)(C~E)(DFS、数论(容斥)、SCC缩点 + DAG图上DP)



​​​​​​1900C - Anji's Binary Tree 

        题意:

凯克西奇一直被安吉冷落。通过一个共同的朋友,他发现安吉非常喜欢二叉树,于是决定解决她的问题,以引起她的注意。Anji 给了 Keksic 一棵有 n个顶点的二叉树。顶点 1 是根,没有父顶点。所有其他顶点都有一个父顶点。每个顶点最多可以有 2个子顶点、一个左子顶点和一个右子顶点。对于每个顶点,安吉都会告诉凯西奇它的左子和右子的索引,或者告诉他它们不存在。

此外,每个顶点上都有一个字母 eq?s_%7Bi%7D,即 "U"、"L "或 "R"。

克克西奇从根开始下棋,他的每一步都是这样走的:

  • 如果当前顶点上的字母是 "U",他就移动到它的父顶点。如果它不存在,他就什么也不做。
  • 如果当前顶点上的字母是 "L",则移动到其左侧子顶点。如果它不存在,则他什么也不做。
  • 如果当前顶点上的字母是 "R",则移动到其右边的子顶点。如果它不存在,则他什么也不做。

在移动之前,他可以执行以下操作:选择任意一个节点,并用另一个节点替换写在上面的字母。

我们想知道的是,当他开始旅行时,他将在某一点到达一片叶子,那么他在旅行前需要做的操作的最小数目。叶子是一个没有子顶点的顶点。他到达哪片叶子并不重要。需要注意的是,他是否会停留在叶子上并不重要,他只需要移动到叶子上。此外,他需要移动多少次才能到达一片叶子也无关紧要。

帮助 Keksic 解开安吉的树,这样他就能赢得她的芳心,让她来到恰恰克。

        思路:转化为到叶子结点最短路,若顶点字母是‘L’,则到达左孩子路径长度为0,若顶点是‘R’,则到达右边孩子长度为0,否则都是1(代表了需要修改),求到达叶子结点路径最小值。

        

// Problem: C. Anji's Binary Tree
// Contest: Codeforces - Codeforces Round 911 (Div. 2)
// URL: https://codeforces.com/contest/1900/problem/C
// Memory Limit: 256 MB
// Time Limit: 2500 ms
// 
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second 
#define endl '\n'
const LL maxn = 4e05+7;
const LL N = 5e05+10;
const LL mod = 1e09+7;
const int inf = 0x3f3f3f;
const LL llinf = 5e18;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){return b > 0 ? gcd(b , a % b) : a;
}LL lcm(LL a , LL b){return a / gcd(a , b) * b;
}
int n , m;
int a[N];
void init(int n){for(int i = 0 ; i <= n ; i ++){a[i] = 0;}
}
struct Node{int l ,  r;
}e[N];
void solve() 
{cin >> n;string s;cin >> s;s = " " + s;
//	cout << s[1]<<endl;for(int i = 1 ; i <= n ; i ++){cin >> e[i].l >> e[i].r;	}int ans = inf;queue< pair<int,int>>q;q.push({1 , 0});while(!q.empty()){auto tmp = q.front();q.pop();int id = tmp.x , dis = tmp.y;
//		cout << id << dis << endl;if(e[id].l != 0){int nex = e[id].l;if(s[id] != 'L'){q.push({nex , dis + 1});}else{q.push({nex , dis});}}if(e[id].r != 0){int nex = e[id].r;if(s[id] != 'R'){q.push({nex , dis + 1});}else{q.push({nex , dis});}			}if(e[id].l == 0 && e[id].r == 0){ans = min(ans , dis);}}cout << ans << endl;
}            
int main() 
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cout.precision(10);int t=1;cin>>t;while(t--){solve();}return 0;
}

 1900D - Small GCD 

(太菜了导致坐牢一个半小时,没想到能够预处理因子的价值,下次不会再犯了)

        题意:设 a 、 b 和 c 为整数。函数 f(a,b,c) 的定义如下:将数字 a 、 b 、 c 排序为 a≤b≤c 。然后返回 gcd(a,b) ,其中 gcd(a,b) 表示整数 a 和 b 的 最大公约数 (GCD)。给你一个由 n 个元素组成的数组 a 。计算每个 i 、 j 、 k 的 f(ai,aj,ak) 和,使得 1≤i<j<k≤n 。更正式地说,计算

eq?%5Csum_%7Bi%20%3D%201%7D%5E%7Bn%7D%20%5Csum_%7Bj%20%3D%20i%20&plus;%201%7D%5E%7Bn%7D%20%5Csum_%7Bk%20%3D%20j%20&plus;%201%7D%5E%7Bn%7Df%28a_%7Bi%7D%2Ca_%7Bj%7D%2C%20a_%7Bk%7D%29

        思路:当对a数组进行排序以后会发现,原式子eq?%5Csum_%7Bi%20%3D%201%7D%5E%7Bn%7D%20%5Csum_%7Bj%20%3D%20i%20&plus;%201%7D%5E%7Bn%7D%20%5Csum_%7Bk%20%3D%20j%20&plus;%201%7D%5E%7Bn%7Df%28a_%7Bi%7D%2Ca_%7Bj%7D%2C%20a_%7Bk%7D%29的k变成了一个无效的东西(因为eq?a_%7Bi%7D%20%5Cleq%20a_%7Bj%7D%5Cleq%20a_%7Bk%7D)。原式子变为\sum_{i = 1}^{n} \sum_{j = i + 1}^{n} gcd(a_{i},a_{j})*(n - j)

再转化一下得到eq?%5Csum_%7Bi%20%3D%201%7D%5E%7Bj%20-%201%7D%20%5Csum_%7Bj%20%3D%202%7D%5E%7Bn%7D%20gcd%28a_%7Bi%7D%2Ca_%7Bj%7D%29*%28n%20-%20j%29.。对于这种所有区间求和问题,考虑右端点递增,然后思考如何去维护左侧所有区间的信息。首先我们如果单纯的两两求gcd肯定是不行的,观察数据后发现a数组的数据很小,也就是说a的因子个数很小。而两个数的gcd也就是他们的最大公共因子。因此可以考虑统计区间内所有因子的个数,然后对于每个右端点eq?a_%7Bj%7D而言,遍历其所有因子,区间之和就是(右端点的因子大小 * 区间内该因子的个数)的总和。但是仔细想想之后发现是有重复的:假如当前因子是2,用2 * 区间内2的因子个数是不正确的,因为有2这个因子也必然会有1这个因子。gcd是两个数的最大公共因子,所以统计因子2时会把1这个因子给撤销掉,后面任意因子也是同理。也就是说,2这个因子的实际价值不是2而是1。3也是同理,3的实际价值需要减去1的实际价值, 而6的实际价值需要减去1、2、3实际价值。因此对于任意一个因子而言,其实际价值需要需要减去其所有不为他本身的因子的实际价值。

        对于每个数的因子,每个因子的实际价值都是可以预处理出来的。做的时候只需要过一下公式即可。

        

// Problem: D. Small GCD
// Contest: Codeforces - Codeforces Round 911 (Div. 2)
// URL: https://codeforces.com/contest/1900/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second 
#define endl '\n'
const LL maxn = 4e05+7;
const LL N = 1e05+10;
const LL mod = 1e09+7;
const int inf = 0x3f3f;
const LL llinf = 5e18;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){return b > 0 ? gcd(b , a % b) : a;
}LL lcm(LL a , LL b){return a / gcd(a , b) * b;
}
int n , m;
int a[N];
void init(int n){for(int i = 0 ; i <= n ; i ++){a[i] = 0;}
}
int cnt[N];
vector<int>yinzi[100010];
int val[N];
void solve() 
{memset(cnt , 0 , sizeof cnt);cin >> n;for(int i = 0 ; i < n ; i ++)cin >> a[i];sort(a , a + n);LL ans = 0;for(int i = 0 ; i < n - 1; i ++){LL sum = 0;for(auto it : yinzi[a[i]])sum += 1LL * val[it] * cnt[it];ans += sum * (n - i - 1);for(auto it : yinzi[a[i]]){cnt[it]++;}		}cout << ans <<endl;
}            
int main() 
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cout.precision(10);int t=1;int maxx = -1;auto cmp = [&](int x , int y){return x > y;};for(int i = 1 ; i <= 100000 ; i ++){val[i] = i;yinzi[i].pb(i);}for(int i = 1 ; i <= 100000; i ++){for(int j = i * 2; j <= 100000 ; j += i){yinzi[j].pb(i);val[j] -= val[i];}}cin>>t;while(t--){solve();}return 0;
}

        

E - Transitive Graph 

        (补的时候发现就是个SCC缩点 + DAG图上DP问题)

     题意:给你一个有向图 G ,其中有 n 个顶点和 m条边。

最初,图 H与图 G相同。然后,您决定执行以下操作:

  • 如果存在由顶点 a 、 b 、 c 和 H 组成的三重顶点,且存在一条从 a 到 b 的边和一条从 b 到 c 的边,但没有从 a 到 c 的边,则添加一条从 a 到 c的边。
  • 只要存在这样的三边形,就重复上一步。

注意,执行上述操作后, H中的边的数量最多可达 eq?n%5E2

您还在图 H的顶点上写了一些值。更确切地说,在顶点 i 上写入了 ai的值。

考虑一条由 k个顶点组成的简单路径。索引为 v1,v2,…,vk 的个不同顶点组成的简单路径。这条路径的长度为 k 。该路径的值定义为 eq?%5Csum%20_%7Bi%20%3D%201%7D%5Eka_%7Bv_%7Bi%7D%7D

如果图中没有其他更长的简单路径,那么这条简单路径就是最长的。

在 H中所有最长的简单路径中,找出数值最小的一条。

        思路:观察题目中的操作,其实就是把有向图中一条路径上的点全部两两相连,其实这样操作在求最长简单路径时没有任何意义,因为a到c增加的边在求最长路径时必然会被a到b,b到c这两条边代替。这么做保证了能从一个强连通分量上的任意一点连到其他强连通分量上的任意一点。因此本题就变成了给定一个有向图求最长简单路径中权值最小的那一条。直接强连通分量缩点 + 图上DP就行,用tarjan求出scc,然后按照逆拓扑序dp就行。

        

// Problem: E. Transitive Graph
// Contest: Codeforces - Codeforces Round 911 (Div. 2)
// URL: https://codeforces.com/contest/1900/problem/E
// Memory Limit: 256 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second 
#define endl '\n'
const LL maxn = 4e05+7;
const LL N = 5e05+10;
const LL mod = 1e09+7;
const int inf = 0x3f3f;
const LL llinf = 5e18;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){return b > 0 ? gcd(b , a % b) : a;
}LL lcm(LL a , LL b){return a / gcd(a , b) * b;
}
int n , m;
LL a[N];
vector<int>e[N];
int dfn[N] , low[N] , ins[N] , idx = 0 , cnt = 0, bel[N];//dfn : dfs的时间戳 low : 子树能跳到的最上方的点 bel : 结点位于哪块强连通分量上
stack<int>stk;
int out[N];
int x[N] , y[N] , ty[N] , ans = 0;
pair<LL,LL>dp[N];
void init(int n){idx = cnt = 0;for(int i = 0 ; i <= n ; i ++){a[i] = 0 , low[i] = 0 , ins[i] = 0 , bel[i] = 0 , dfn[i] = 0 , e[i].clear();}
}
void tarjan(int u , int fa){//无向图需要fa != udfn[u] = low[u] = ++idx;//dfs序中的顺序ins[u] = true;//是否在栈当中stk.push(u);//未被切掉的点for(auto v : e[u]){if(!dfn[v]){tarjan(v , u);low[u] = min(low[u] , low[v]);}else{//被访问过了if(ins[v]){low[u] = min(low[u] , dfn[v]);}																																																																																																																																																																							}}if(dfn[u] == low[u]){cnt ++;int sz = 0;LL ch = 0;LL sum = 0;dp[cnt] = {0 , 0};while(true){int v = stk.top();bel[v] = cnt;ch ++;sum += a[v];ins[v] = false;for(int w : e[v]){if(bel[w] != cnt && bel[w] != 0){if(dp[bel[w]].x > dp[cnt].x){dp[cnt] = dp[bel[w]];}else if(dp[bel[w]].x == dp[cnt].x && dp[bel[w]].y < dp[cnt].y){dp[cnt] = dp[bel[w]];}}}stk.pop();if(v == u){break;}}dp[cnt].x += ch;dp[cnt].y += sum;}
}
void solve() 
{cin >> n >> m;map<pair<int,int>,int>mp;for(int i = 1 ; i <= n ; i ++)cin >> a[i];for(int i = 0 ; i < m ; i ++){int x , y;cin >> x >> y;if(mp.count({x , y}) || x == y){continue;}else{e[x].pb(y);mp[{x,y}] = 1;}}for(int i = 1 ; i <= n ; i++){if(!dfn[i]) tarjan(i , 0);}
/*	for(int i = 1 ; i <= n ; i ++){cout << bel[i] << endl;}*/pair<LL,LL>ans = {0 , 0};for(int i = 1 ; i <= cnt ; i ++){if(dp[i].x > ans.x){ans = dp[i];}else if(dp[i].x == ans.x && dp[i].y < ans.y){ans = dp[i];}}init(n);cout << ans.x << " " << ans.y << endl;
}            
int main() 
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cout.precision(10);int t=1;cin>>t;while(t--){solve();}return 0;
}

        

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

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

相关文章

利用异或、取反、自增bypass_webshell_waf

目录 引言 利用异或 介绍 eval与assert 蚁剑连接 进阶题目 利用取反 利用自增 引言 有这样一个waf用于防御我们上传的文件&#xff1a; function fun($var): bool{$blacklist ["\$_", "eval","copy" ,"assert","usort…

Vue+SpringBoot解决session跨域问题

做了一个前后端分离&#xff0c;因为前后端的 session id不一致&#xff0c;导致前端请求时&#xff0c;后端的session读取不到对应的值&#xff0c;造成登录问题。 解决方法&#xff1a; SpringBoot项目: 添加一个跨域配置 代码如下: 或者controller使用CrossOrigin Conf…

No matching version found for @babel/compat-data@^7.23.5 处理

npm ERR! notarget No matching version found for babel/compat-data^7.23.5 处理 报错信息 npm WARN ERESOLVE overriding peer dependency npm ERR! code ETARGET npm ERR! notarget No matching version found for babel/compat-data^7.23.5. npm ERR! notarget In most …

【java】编译时bug 项目启动前bug合集

文章目录 1. jdk8中 Optional orElseThrow 编译时报错java: 未报告的异常错误X; 必须对其进行捕获或声明以便抛出2. 启动项目时提示 Error running Application: Command line is too long. Shorten command line for Application or also for Spring Boot default configurati…

算法学习—排序

排序算法 一、选择排序 1.算法简介 选择排序是一个简单直观的排序方法&#xff0c;它的工作原理很简单&#xff0c;首先从未排序序列中找到最大的元素&#xff0c;放到已排序序列的末尾&#xff0c;重复上述步骤&#xff0c;直到所有元素排序完毕。 2.算法描述 1&#xff…

万宾科技监测设备,可燃气体监测仪特点一览

万宾科技的监测设备种类繁多&#xff0c;包括可燃气体监测仪、管网水位监测仪、内涝积水监测仪等。其中可燃气体监测仪是万宾科技的核心产品之一&#xff0c;用于监测环境中可燃气体的浓度&#xff0c;适用于对甲烷气体浓度进行实时监测&#xff0c;应用于燃气管网、排水管网、…

从cmd登录mysql

说明 先看看mysql.exe文件在哪个目录下&#xff0c;为了后面的操作方便&#xff0c;可以将该文件所在的路径增加到环境变量path中。 如果不增加到path环境变量中&#xff0c;那么在cmd窗口就要切换到mysql.exe文件所在的目录下执行。 在cmd窗口查看mysql命令的帮助信息 在cm…

编译原理:设计与实现一个简单词法分析器

设计与实现一个简单词法分析。具体内容是产生一个二元式文本文件&#xff0c;扩展名为dyd&#xff0c;可将Java或C程序(测试程序)分解成为一个一个的单词及类型。 &#xff08;选做&#xff1a;并查“单词符号与种别对照表”得出其种别&#xff0c;用一数字表示。&#xff09;…

CSS 多主题切换思路

前言 本篇仅提供多主题切换思路&#xff0c;示例简单且清晰。 实现 步骤一&#xff1a;多主题(颜色)定义 定义根伪类 :root&#xff0c;代码第 2 和 7 行。分别定义了默认和带参数的伪类&#xff1b;定义 CSS 变量&#xff0c;注意变量名需要以两个减号&#xff08;--&…

adb修改android系统时间 adb shell date必须要root权限

adb Command adb root //需要root权限 adb shell setprop persist.sys.timezone GMT //校准时区 adb shell date MMDDhhmmYY.ss set //修改系统时间这里是GMT格林尼治时间&#xff0c;北京时间得转换一下 8小时 adb shell hwclock -w //同步硬件时间adb shell date 0201030422…

初识Linux:权限

目录 提示&#xff1a;以下指令均在Xshell 7 中进行 Linux 的权限 内核&#xff1a; 查看操作系统版本 查看cpu信息 查看内存信息 外部程序&#xff1a; 用户&#xff1a; 普通用户变为超级用户&#xff1a; su 和 su-的区别&#xff1a; root用户变成普通用户&#…

机器人最优控制开源库 Model-based Optimization for Robotics

系列文章目录 文章目录 系列文章目录前言一、开源的库和工具箱1.1 ACADO1.2 CasADi1.3 Control Toolbox1.4 Crocoddyl1.5 Ipopt1.6 Manopt1.7 LexLS1.8 NLOpt1.9 qpOASES1.10 qpSWIFT1.11 Roboptim 二、其他库和工具箱2.1 MUSCOD2.2 OCPID-DAE12.3 SNOPT 前言 机器人&#xff…

【论文阅读】1 SkyChain:一个深度强化学习的动态区块链分片系统

SkyChain 一、文献简介二、引言及重要信息2.1 研究背景2.2 研究目的和意义2.3 文献的创新点 三、研究内容3.1模型3.2自适应分类账协议3.2.1状态块创建3.2.2合并过程3.2.3拆分过程 3.3评价框架3.3.1性能3.3.1.1共识延迟3.3.1.2重新分片延迟3.3.1.3处理事务数3.3.1.4 约束 3.3.2 …

【代码】基于麻雀搜索优化Kmeans图像分割算法

程序名称&#xff1a;基于麻雀搜索优化Kmeans图像分割算法 实现平台&#xff1a;matlab 代码简介&#xff1a;首先使用麻雀搜索优化算法来确定 K-means 算法的初始质心位置&#xff0c;然后进行传统的 K-means 聚类。这样做的目的是为了避免 K-means 算法陷入局部最优解&…

使用Docker安装部署Swagger Editor并远程访问编辑API文档

文章目录 Swagger Editor本地接口文档公网远程访问1. 部署Swagger Editor2. Linux安装Cpolar3. 配置Swagger Editor公网地址4. 远程访问Swagger Editor5. 固定Swagger Editor公网地址 Swagger Editor本地接口文档公网远程访问 Swagger Editor是一个用于编写OpenAPI规范的开源编…

还得是字节出来的,太秀了...

前段时间公司缺人&#xff0c;也面了许多测试&#xff0c;一开始瞄准的就是中级水准&#xff0c;当然也没指望能来大牛&#xff0c;提供的薪资在15-20k这个范围&#xff0c;来面试的人有很多&#xff0c;但是平均水平真的让人很失望。看了简历很多上面都是写有4年工作经验&…

MatrixOne Meetup回顾 | 深圳站

11月11日&#xff0c;MatrixOne 社区在深圳成功举办了第二次 MatrixOne Meetup。活动当天&#xff0c;数十位外部小伙伴到场参与&#xff0c;一同分享云原生数据库相关知识内容。此次活动&#xff0c;我们也邀请了来自深圳素问智能的外部讲师&#xff0c;分享了目前火爆的大模型…

【每日OJ —— 144. 二叉树的前序遍历】

每日OJ —— 144. 二叉树的前序遍历 1.题目&#xff1a;144. 二叉树的前序遍历2.方法讲解2.1.算法讲解2.2.代码实现2.3.提交通过展示 1.题目&#xff1a;144. 二叉树的前序遍历 2.方法讲解 2.1.算法讲解 1.首先如果在每次每个节点遍历的时候都去为数组开辟空间&#xff0c;这样…

steam搬砖项目到底能不能做?

在Steam的世界里&#xff0c;有一款引人注目的游戏——《CSGO》游戏设备和配件的搬运项目。它就像一个桥梁&#xff0c;连接着全球的游戏世界&#xff0c;为玩家们提供着精彩的设备和配件。原则上&#xff0c;这是一个低买高卖的过程&#xff0c;通过汇率差来赚取利润。比如&am…

从PDF和图像中提取文本,以供大型语言模型使用

想法 大型语言模型已经席卷了互联网&#xff0c;导致更多的人没有认真关注使用这些模型最重要的部分&#xff1a;高质量的数据&#xff01;本文旨在提供一些有效从任何类型文档中提取文本的技术。 Python库 本文专注于Pytesseract、easyOCR、PyPDF2和LangChain库。实验数据是一…