没有手速,再加上被 E 卡了,废掉了。

A.GamingForces

题目描述:

Monocarp 正在玩电脑游戏。他打算杀死 \(n\) 个怪兽,第 \(i\) 个的血量为 \(h_i\)。

Monocarp 的角色有两个魔法咒语如下,都可以以任意顺序用任意次(可以不用),每次使用相当于一次操作。

  1. 选择两个怪兽并扣一滴血。

  2. 选择一个怪兽并且直接杀死。

当一个怪兽血量为 \(0\) 时,他死了

求杀死所有怪兽的最少操作次数。

题目分析:

只有两个怪兽同为 \(1\) 点血,这个时候我们通过 \(1\) 操作直接把它们弄死才会比直接通过操作 \(2\) 直接弄死更优。

所以判一下这个就好了。

代码:

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 10005;
int a[N];
int main(){
int T;scanf("%d",&T);
while(T--){
int n;scanf("%d",&n);
for(int i=1; i<=n; i++) scanf("%d",&a[i]);
int cnt = 0;
for(int i=1; i<=n; i++){
if(a[i] == 1) ++cnt;
}
printf("%d\n",n - cnt / 2);
}
return 0;
}

B.Stand-up Comedian

题目描述:

Eve 是个单口相声新手。她的第一场表演聚集了总计 \(2\) 个观众:Alice 和 Bob。

Eve 准备了 \(a_1+a_2+a_3+a_4\) 个相声表演节目。\(a_i\) 表示第 \(i\) 类相声的数目,每类的的特征如下:

  1. Alice 和 Bob 都喜欢这类相声。

  2. Alice 喜欢,Bob 不喜欢。

  3. Bob 喜欢,Alice 不喜欢。

  4. Alice 和 Bob 都不喜欢这类相声。

一开始,两位观众的心情都为 \(0\)

当一位观众听到他喜欢的相声表演时心情会加 \(1\),当听到的是自己不喜欢的相声时,心情减 1

当某位观众心情严格小于 \(0\) 时,这位观众会离场。只要有一位这样的观众离场,Eve 会特别伤心并且结束整个表演。若演完了所有节目,也会结束表演。

求某种安排表演顺序的方式,使得 Eve 在结束表演前能表演的节目最多。输出最多能表演的节目数。

译者注:若演完某个节目有观众退场,这个节目也算在总数之中

\(0 \le a_1,a_2,a_3,a_4 \le 10^8\)。

题目分析:

好像是个大细节题,但是我一遍过就很爽[狂笑]

考虑最优的一个操作顺序肯定是:\(1 \to 2,3 \to 4\)。

关键是中间 \(2,3\) 造成的贡献比较难算,可以显然发现我们先操作一次 \(2\) 后操作一次 \(3\) 它们的代价就抵消了,而且会多出两次节目,但是要注意如果 \(1\) 操作数量为 \(0\) 就不能相互抵消了。

所以就按照:操作 \(1\)、\(2,3\) 抵消、操作 \(2,3\)、操作 \(4\),这样的顺序模拟一下即可。

代码:

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int cnt[10];
signed main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int T;scanf("%lld",&T);
while(T--){
for(int i=1; i<=4; i++) scanf("%lld",&cnt[i]);
int ans = 0;
int a = cnt[1],b = cnt[1];ans += cnt[1];
if(a == 0){
if(cnt[2] + cnt[3] + cnt[4] > 0) printf("1\n");
else printf("0\n");
continue;
}
int tmp = min(cnt[2],cnt[3]);ans += 2 * tmp;
cnt[2] -= tmp,cnt[3] -= tmp;
if(cnt[2] > 0){
tmp = min(cnt[2],b+1);ans += tmp;
a += tmp,b -= tmp;
}
if(cnt[3] > 0){
tmp = min(cnt[3],a+1);ans += tmp;
a -= tmp,b += tmp;
}
if(a >= 0 && b >= 0){
ans += min(min(a+1,b+1),cnt[4]);
}
printf("%lld\n",ans);
}
return 0;
}

C.Min Max Sort

题目描述:

对于一个排列,定义一次操作为:在排列中任选两个数字,将它们中的最大值插入至队尾,最小值插入至队首。

现在给定多个排列,问每个排列最少各需多少次操作才能变得严格递增。

\(1 \le n\le 2\times 10^5\)

题目分析:

如果我们要进行操作,那么最后 \(1\) 操作必然是 \(1,n\),然后倒推一下就会发现倒数第 \(2\) 次操作必然是 \(2,n-1\),然后就可以发现倒数第 \(i\) 次操作必然是 \(i,n-i+1\)。

所以假设我们通过 \(k\) 次操作可以使排列严格递增,也就是说值在 \([k+1,n-k]\) 是不用我们管的了,已经符合条件了,将两头的 \(k\) 个进行排完序就结束了。

这个“不用管”用形式化的语言说其实就是,设 \(pos_i\) 表示数 \(i\) 出现的位置,则 \(pos_{k+1} < pos_{k+2} < \cdots < pos_{n-k}\)。

所以可以直接一个个枚举 \(k\) 判断是否合法即可,也就是将 \(k\) 从 \(\lfloor \frac{n}{2} \rfloor\) 开始依次减 \(1\),然后判断条件是否满足。

代码:

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
int a[N],p[N];
int main(){
int T;scanf("%d",&T);
while(T--){
int n;scanf("%d",&n);
for(int i=1; i<=n; i++) scanf("%d",&a[i]),p[a[i]] = i;
int k = n / 2;
while(k && p[k] < p[k+1] && p[n-k] < p[n-k+1]) --k;
printf("%d\n",k);
}
return 0;
}

D.Fixed Prefix Permutations

题目描述:

对于一个排列 \(p\),定义其美丽度 \(k\) 为

  • \(p_1=1,p_2=2,\cdots,p_k=k,p_{k+1} \neq k+1\)

若 \(p,q\) 均为长度为 \(n\) 的排列,定义排列的运算 \(p \cdot q\) 为:

  • \(p \cdot q = r\),\(p,q,r\) 均为长度为 \(n\) 的排列
  • \(r_j = q_{p_j}\)

现在给出 \(n\) 个长度为 \(m\) 的排列,对于每一个 \(a_i\),求 \(a_i \cdot a_j(1 \le j \le n)\) 美丽值最大为多少,允许有 \(i=j\)。

多测,\(T \le 10^4\),\(\sum n \le 5 \times 10^4\),\(m \le 10\)

题目分析:

考虑如果就是给定了两个排列 \(p,q\) 怎么算它的美丽值。

要让 \(i\) 经过两个排列的置换后依旧是在 \(i\) 的位置,其实就是说设 \(pos_i\) 表示 \(i\) 在 \(q\) 中的位置,则 \(p_i = pos_i\),可以将置换理解为走路这种东西然后就很好理解了。

所以其实就是求出 \(pos\) 之后两者的 \(lcp\)。

那么这个题就很好解决了,可以直接对于每一个排列都求出 \(pos\),然后插入到 trie 树里,计算答案就是枚举每一个排列然后让它在字典树上走即可。

(我竟然一开始用了 bitset 维护这个过程,差点就过了)

代码:

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 5e4+5;
int n,m,a[N][11],tot = 1,pos[N][11],ch[100 * N][11];
void insert(int x){
int now = 1;
for(int i=1; i<=m; i++){
int to = pos[x][i];
if(!ch[now][to]) ch[now][to] = ++tot;
now = ch[now][to];
}
}
int find(int x){
int now = 1;
int ans = 0;
for(int i=1; i<=m; i++){
if(ch[now][a[x][i]]){
++ans,now = ch[now][a[x][i]];
}
else break;
}
return ans;
}
int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int T;scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
scanf("%d",&a[i][j]);
pos[i][a[i][j]] = j;
}
insert(i);
}
for(int i=1; i<=n; i++) printf("%d ",find(i));
printf("\n");
for(int i=1; i<=tot; i++){
for(int j=1; j<=10; j++){
ch[i][j] = 0;
}
}
tot = 1;
}
return 0;
}

E.Divisors and Table

题目描述:

给定一张 \(n \times n\) 的表格和一个正整数 \(m = m_1 \times m_2\),表格第 \(i\) 行第 \(j\) 列的数 \(a_{i, j} = i \times j\)。

现在需要你求出 \(m\) 的每个因子 \(d\) 是否在表格中出现,若出现,则求出其出现在表格中的最小行号。

\(1 \le n, m_1, m_2 \le 10^9\)

题目分析:

(一种乱搞做法)

\(10^{18}\) 以内的数,因子个数最多有大约 \(10^5\) 个,所以显然可以将 \(m\) 的的所有因子都拿出来然后挨个判断。

要求所有的因子其实就是要对 \(m\) 质因数分解,可以直接用科技对 \(m\) 分解,也可以分别为 \(m_1,m_2\) 分解后合起来,这样我们就得到了 \(m\) 的所有因子。

我们要做的其实就是分解 \(d = a \times b\),且 \(a,b \le n\),要求 \(a\) 尽可能小。

因为 \(d\) 为 \(m\) 的因子,所以 \(a,b\) 也必然是 \(m\) 的因子,所以可以将因子排序之后二分。

具体来说就是二分最小的 \(a\) 使得 \(\lceil \frac{d}{a} \rceil \le n\),这样只需要向后枚举一些 \(a\) 使得 \(a \mid d\) 此时 \(a\) 就是最优的 \(a\) 了。

代码:

点击查看代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector> using namespace std; #define int long long int t, n, m1, m2;
vector<int> a, b, c; signed main()
{
scanf("%lld", &t);
while (t -- )
{
int cnt = 0, ans = 0;
a.clear();
b.clear();
c.clear(); scanf("%lld%lld%lld", &n, &m1, &m2);
for (int i = 1; i <= m1 / i; i ++ )
{
if(m1 % i == 0)
{
a.push_back(i);
if(m1 / i != i) a.push_back(m1 / i);
}
}
for (int i = 1; i <= m2 / i; i ++ )
{
if(m2 % i == 0)
{
b.push_back(i);
if(m2 / i != i) b.push_back(m2 / i);
}
}
sort(a.begin(), a.end());
sort(b.begin(), b.end()); for (int i = 0; i < a.size(); i ++ )
for (int j = 0; j < b.size(); j ++ )
c.push_back(a[i] * b[j]); sort(c.begin(), c.end());
c.erase(unique(c.begin(), c.end()), c.end()); for (int i = 0; i < c.size(); i ++ )
{
int l = 0, r = i;
while (l <= r)
{
int mid = l + r >> 1;
if ((c[i] + c[mid] - 1) / c[mid] <= n) r = mid - 1;
else l = mid + 1;
}
for (int j = l; j < c.size(); j ++ )
{
if(c[j] > n) break;
if(c[i] % c[j] == 0)
{
ans ^= c[j];
cnt ++;
break;
}
}
}
printf("%lld %lld\n", cnt, ans);
}
}

F1.Graph Coloring

题目描述:

简单版和困难版之间的唯一区别是 \(n\) 的数据范围不同。

给出一个 \(n\) 个顶点的无向完全图。完全图是指图上任意两个顶点皆有一条边相连。你需要给图上的每条边染上红色或蓝色。

一个顶点的集合 \(S\) 被称作是红色连接的,如果对于 \(S\) 中每对顶点 \((v_1,v_2)\),都存在只通过红边和 \(S\) 中顶点的路径。相仿地,一个顶点的集合 \(S\) 被称作是蓝色连接的,如果对于 \(S\) 中每对顶点 \((v_1,v_2)\),都存在只通过蓝边和 \(S\) 中顶点的路径。

你需要以如下方式对图进行染色:

  • 至少有一条红边。
  • 至少有一条蓝边。
  • 对于每个大小不小于 \(2\) 的顶点集 \(S\)(也即 \(|S|\geqslant 2\)),\(S\) 或者是红色连接的,或者是蓝色连接的,但不能同时是红色和蓝色连接的。

计算染色方法数对 \(998244353\) 取模后的结果。

\(1\le n \le 5\times 10^3\)

题目分析:

(不写 F2 了,是一个多项式科技)

题目条件就是要求对于任意一个导出子图,要么通过红色边可以联通,要么通过蓝色边可以联通,但是不能通过两种边都可以联通。

注意到一点就是:这是一个完全图,所以蓝色边和红色边互为补图,也就是如果蓝色边不连通则红色边必然联通,反之亦然。

所以我们可以直接 \(dp_n\) 表示节点个数为 \(n\) 的图,不能通过蓝色边联通的合法的方案数。

转移就是考虑枚举点 \(n\) 所在的蓝色连通块大小 \(x\):

\[dp_n = \sum_{x=1}^{n-1} \binom{n-1}{x-1} dp_x \times (2 - [x = n-1])dp_{n-x}
\]

对于 \(n\) 所在的连通块这 \(x\) 个点必然满足蓝色联通也就是红色不连通,方案数等同于 \(dp_x\)。

对于其余的 \(n-x\) 个点,它们之间蓝色联通或者红色联通都可以,所以就是系数有 \(2\) 的贡献,但当 \(n-x = 1\) 时,显然只有一种方案。

因为题目要求必须同时出现红边和蓝边,所以将答案减 \(2\) 即可。

代码:

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e3+5;
const int MOD = 998244353;
int fac[N],inv[N],f[N];
int binom(int n,int m){
if(n < m || n < 0 || m < 0) return 0;
return fac[n] * inv[m] % MOD * inv[n-m] % MOD;
}
int power(int a,int b){
int res = 1;
while(b){
if(b & 1) res = res * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return res;
}
signed main(){
int n;scanf("%lld",&n);
fac[0] = 1;
for(int i=1; i<=n; i++) fac[i] = fac[i-1] * i % MOD;
inv[n] = power(fac[n],MOD-2);
for(int i=n-1; i>=0; i--) inv[i] = inv[i+1] * (i+1) % MOD;
f[1] = 1;
for(int i=2; i<=n; i++){
for(int j=1; j<=i-1; j++){
f[i] = (f[i] + f[j] * f[i-j] %MOD* binom(i-1,j-1) * (2 - (j == i-1))%MOD)%MOD;
}
}
printf("%lld\n",(2 * f[n] %MOD - 2 + MOD)%MOD);
return 0;
}

【题解】Educational Codeforces Round 142(CF1792)的更多相关文章

  1. Educational Codeforces Round 142 (Rated for Div. 2) A-D

    比赛链接 A 题解 知识点:贪心. 代码 #include <bits/stdc++.h> using namespace std; using ll = long long; bool ...

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

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

  3. Educational Codeforces Round 48 (Rated for Div. 2) CD题解

    Educational Codeforces Round 48 (Rated for Div. 2) C. Vasya And The Mushrooms 题目链接:https://codeforce ...

  4. Educational Codeforces Round 60 (Rated for Div. 2) 题解

    Educational Codeforces Round 60 (Rated for Div. 2) 题目链接:https://codeforces.com/contest/1117 A. Best ...

  5. Educational Codeforces Round 59 (Rated for Div. 2) DE题解

    Educational Codeforces Round 59 (Rated for Div. 2) D. Compression 题目链接:https://codeforces.com/contes ...

  6. Educational Codeforces Round 58 (Rated for Div. 2) 题解

    Educational Codeforces Round 58 (Rated for Div. 2)  题目总链接:https://codeforces.com/contest/1101 A. Min ...

  7. Educational Codeforces Round 65 (Rated for Div. 2)题解

    Educational Codeforces Round 65 (Rated for Div. 2)题解 题目链接 A. Telephone Number 水题,代码如下: Code #include ...

  8. Educational Codeforces Round 64 (Rated for Div. 2)题解

    Educational Codeforces Round 64 (Rated for Div. 2)题解 题目链接 A. Inscribed Figures 水题,但是坑了很多人.需要注意以下就是正方 ...

  9. Educational Codeforces Round 64 部分题解

    Educational Codeforces Round 64 部分题解 不更了不更了 CF1156D 0-1-Tree 有一棵树,边权都是0或1.定义点对\(x,y(x\neq y)\)合法当且仅当 ...

  10. Educational Codeforces Round 64部分题解

    Educational Codeforces Round 64部分题解 A 题目大意:给定三角形(高等于低的等腰),正方形,圆,在满足其高,边长,半径最大(保证在上一个图形的内部)的前提下. 判断交点 ...

随机推荐

  1. Sublime Text Windows/Linux平台快捷键

    编辑 按键 对应命令 Ctrl + X 删除行 Ctrl + 行后插入 Ctrl + ⇧ + 行前插入 Ctrl + ⇧ + ↑ 上移文本/选择 Ctrl + ⇧ + ↓ 下移文本/选择 Ctrl + ...

  2. 文档在线预览(三)使用js前端实现word、excel、pdf、ppt 在线预览

    @ 目录 实现方案 一.docx文件实现前端预览 1.docx-preview 2.Mammoth 二.PDF文件实现前端预览 1.pdf.js 2.pdfobject.js 3.vue-pdf 4. ...

  3. CF1583H Omkar and Tours 题解

    题意: 给定一个 \(n\) 个点的树,每条边有权值 \(t\) 和 \(c\).一条路径的权值为所经过节点的 \(\max(c)\). 每个点有权值 \(e\). 给出 \(q\) 个询问,每次询问 ...

  4. Galaxy生物信息分析平台的数据集对象清理

    由于微信不允许外部链接,你需要点击文章尾部左下角的 "阅读原文",才能访问文中链接. Galaxy Project 是在云计算背景下诞生的一个生物信息学可视化分析开源项目.该项目由 ...

  5. K8S | 核心原理分析

    目录 一.背景 二.持续集成 三.K8S架构 1.核心组件 2.分层结构 3.核心能力 3.1 发现与负载 3.2 调度 3.3 自动伸缩 四.应用案例 1.服务部署 2.交互流程 五.参考源码 整体 ...

  6. Dubbo远程调用在IDEA无法打断点怎么破

     以下是如何在IDEA中在Dubbo的分布式环境中设置远程调试的步骤: 1.首先,你需要在启动提供者服务时,加入一些JVM参数以开启调试服务.这些参数应该在你的启动脚本或者命令中.以下是一个常见的示例 ...

  7. Python的Lambda函数: 一把极简编程的瑞士军刀

    Python中的lambda函数,或者叫匿名函数,是一个极其强大的工具.它以简洁.优雅的语法提供了创建函数的快速方式.在本篇文章中,我们将全方位地深入研究lambda函数的用法和特点,通过理论和实例相 ...

  8. 如何使用Stable Diffusion生成艺术二维码?

    硬件准备 物理内存:至少16G(8G直接安装阶段就卡死) N卡:此处我使用GTX 1660 6G (2019年双12购买) 操作系统 windows 11 软件准备 网络要通畅 git: https: ...

  9. Transformer算法的应用

    目录 1. 引言 2. 技术原理及概念 2.1. 基本概念解释 2.2. 技术原理介绍 2.3. 相关技术比较 3. 实现步骤与流程 3.1. 准备工作:环境配置与依赖安装 3.2. 核心模块实现 4 ...

  10. PRF评价

    PRF评价指标: 精确率P:预测结果正类数量占全部结果的比率: P= $\frac{TP}{TP+FP}$ TP:预测为真且实际为真,FP为预测真实际为假. 召回率R:在所有正类样本中,能回想到的比例 ...