补题与总结:牛客小白月赛83(B~F)

文章目录

    • 写在最前面的复盘
    • B-小天的魔法(贪心 模拟 双指针)
    • C-小天的 Minecraft(概率)
    • D-小天的子序列(预处理 排列组合)
    • E-小天的贪吃蛇(模拟)
    • F-小天的 A+B(结论题)

写在最前面的复盘

image.png
出了ABCD,犯的最大错误就是读假题,ABE都读假了。赛后一想确实读题太急,也没通过用例验证题意
C是一道简单概率题,可能是高中数学考试填空第一题吧,数学忘的太快,概率这块练的也少,好在最后推出来了
赛时却wa穿了D,没想到正解,用了暴力超时,发现答案的数量远远低于询问的数量,想用记忆化优化,接着wa穿。每次读出一个错误就直接交,然后继续wa,还是太着急了,很多代码的细节没有写好就想着交了。赛后看到正解,将 O ( n 2 ) O(n^2) O(n2)的枚举优化到 O ( n ) O(n) O(n)的思路很值得学习
E, O ( n ) O(n) O(n)找下一个不同字符的下标,用set优化成 O ( l n g n ) O(lngn) O(lngn)也值得学习
F,补题时wa穿,对于我目前的实力还是略难了,就算赛时能利用题目性质和数据范围推导出结论,最后的代码实现也会漏掉很多细节,因为要考虑很多边界和结论的性质。但总的来说,推导结论的过程还是值得学习的

B-小天的魔法(贪心 模拟 双指针)

B-小天的魔法_牛客小白月赛83 (nowcoder.com)
image.png

用数组a,b存储题目给定的两个序列,并对其降序排序。用i,j两个指针分别指向a,b数组的第一个元素
贪心思路:考虑使用 b j b_j bj之前是否要使用 a i a_i ai,若 a i a_i ai != 1,则先使用 a i a_i ai再使用 b j b_j bj
证明:使用次数相同时,比较 a i ∗ b j a_i * b_j aibj b j + b j + 1 b_j + b_{j + 1} bj+bj+1的大小。显然 a i a_i ai不为1时,有以下关系
a i ∗ b j > = b j + b j > = b j + b j + 1 a_i * b_j >= b_j + b_j >= b_j + b_{j+1} aibj>=bj+bj>=bj+bj+1
显然使用两次b魔法造成的伤害小于等于先使用a再使用b,证明完毕

注意:若直接使用 b j b_j bj就能击败怪物,则直接使用 b j b_j bj

#include <bits/stdc++.h>
using namespace std;const int N = 3e5 + 10;
int a[N], b[N];void solve()
{int n, m, x; cin >> n >> m >> x;for (int i = 1; i <= n; ++ i) cin >> a[i];for (int i = 1; i <= m; ++ i) cin >> b[i];sort(a + 1, a + n + 1, greater<int>()), sort(b + 1, b + n + 1, greater<int>());int i = 1, j = 1;int cur = 0, cnt = 0;while (j <= m){if (cur >= x) break;// 直接使用b[j]就能击败怪物if (j <= m && cur + b[j] >= x) cur += b[j ++ ], cnt ++ ;// 当a[i] != 1时,贪心else if (i <= n && a[i] != 1) cnt += 2, cur += a[i ++ ] * b[j ++ ];else if (j <= m) cnt ++ , cur += b[j ++ ];}if (cur >= x) cout << cnt << "\n";else cout << "-1\n";
}int main()
{ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);solve();return 0;
}

C-小天的 Minecraft(概率)

C-小天的 Minecraft_牛客小白月赛83 (nowcoder.com)
image.png

生成铜稿首先要12个铜粒,其次需要一个工作台。工作台有三种情况:铜、银、金
铜工作台需要4个铜粒,银的需要4个银粒,金的需要4个金粒
显然,有三种情况能生成铜稿

  • 12个铜粒+铜工作台:16个铜粒
  • 12个铜粒+银工作台:12个铜粒+4个银粒
  • 12个铜粒+金工作台:12个铜粒+4个金粒

假设事件发生的概率为p,重复m次该事件,发生n次p的概率为:
C m n ∗ p n C_m^n * p^n Cmnpn
p a p_a pa p b p_b pb p c p_c pc分别为掉落铜粒、银粒、金粒的概率,那么以上三种情况的概率为:

  • C 16 16 ∗ p a 16 C_{16}^{16} * p_a^{16} C1616pa16
  • C 16 12 ∗ p a 12 + C 16 4 ∗ p b 4 C_{16}^{12} * p_a^{12} + C_{16}^{4} * p_b^4 C1612pa12+C164pb4
  • C 16 12 ∗ p a 12 + C 16 4 ∗ p c 4 C_{16}^{12} * p_a^{12} + C_{16}^{4} * p_c^4 C1612pa12+C164pc4

将三种情况的概率相加即为答案(代码丑陋,看思路自己写就行)

#include <bits/stdc++.h>
using namespace std;void solve()
{int T; cin >> T;while (T --){double a, b, c; cin >> a >> b >> c;a /= 16, b /= 16, c /= 16;double ans = 1;double t = 1;for (int i = 0; i < 12; ++ i) t *= a;for (int i = 0; i < 16; ++ i) ans *= a;double t1 = 1, t2 = 1, t3 = 1;for (int i = 0; i < 4; ++ i) t1 *= a, t2 *= b, t3 *= c;ans += t * (t2 + t3) * 4 * 5 * 7 * 13; // 4 * 5 * 7 * 13为C_16^4的值printf("%.12lf\n", ans);}
}int main()
{solve();return 0;
}

D-小天的子序列(预处理 排列组合)

D-小天的子序列_牛客小白月赛83 (nowcoder.com)
image.png

假设以ch1为开头,ch2为结尾的字符串长度为n,那么满足条件的子序列数量为
C n − 2 l e n − 2 C_{n-2}^{len-2} Cn2len2
根据数据范围,需要预处理组合数 C m n C_m^n Cmn,1<=m <=500, 1<=n<=500
模板为:

for (int i = 0; i < N; ++ i) c[i][0] = 1;
for (int i = 1; i < N; ++ i)for (int j = 1; j <= i; ++ j)c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % 998244353;

接着就是找字符串中的满足条件子串:以ch1为开头,ch2为结尾,且长度大于len
由于字符串最大长度为500,直接暴力预处理字符串所有子串的情况
cnt[26][26][500]保存所有子串的出现次数,如cnt[0][3][2] = 4表示:整个字符串中,以a(0 = a - a)为开头,以d(3 = d - a)为结尾,且长度为2的子串出现了4次

满足条件的子串为cnt[ch1][ch2][t],len <= t <= 500
对于每次的询问,线性枚举t满足条件的子串出现次数并乘以组合数即可

注意:组合数的预处理数组最好开LL

#include <bits/stdc++.h>
using namespace std;const int mod9 = 998244353;
const int N = 510;
long long cnt[30][30][N], c[N][N];void solve()
{int n; cin >> n;string s; cin >> s;s = " " + s;for (int i = 0; i < N; ++ i) c[i][0] = 1;for (int i = 1; i < N; ++ i)for (int j = 1; j <= i; ++ j)c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod9;for (int i = 1; i <= n; ++ i)for (int j = i + 1; j <= n; ++ j)cnt[s[i] - 'a'][s[j] - 'a'][j - i + 1] ++ ;int m; cin >> m;    while (m --){long long ans = 0;char x, y; cin >> x >> y;int len; cin >> len;for (int i = len; i <= n; ++ i)ans = (ans + c[i - 2][len - 2] * cnt[x - 'a'][y - 'a'][i]) % mod9;cout << ans << "\n";}
}int main()
{ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);solve();return 0;
}

E-小天的贪吃蛇(模拟)

E-小天的贪吃蛇_牛客小白月赛83 (nowcoder.com)
image.png

模拟蛇的轨迹,将二维数组转换成一维字符串,保存数组下标与字符串下标之间的映射关系,同时用pos数组保存每个字符在字符串的出现位置(下标)。如pos[1]表示字符b (1 = b - a)在数组中的下标,这些下标用set存储,即set pos[26]

对于修改操作,将二维坐标转换成字符串的下标并修改字符串,同时维护pos数组
对于询问操作,也是将二维坐标转换成字符串的下标,并且获取该下标对应字符。此时在其他字符的出现位置中,找出大于等于(lower_bound)该下标的最小下标,两下标之间的距离为答案

#include <bits/stdc++.h>
using namespace std;typedef pair<int, int> PII;
typedef long long LL;
typedef unsigned long long ULL;
const int inf = 2e9 + 10;
const LL INF = 4e18 + 10;
const int mod9 = 998244353;
const int mod7 = 1e9 + 7;
const int N = 3e5 + 10;
int n, m; 
set<int> pos1[30], pos2[30];void solve()
{cin >> n >> m;vector<vector<char>> g(n + 1, vector<char>(m + 1, 0));vector<vector<int>> idx1(n + 1, vector<int>(m + 1));vector<vector<int>> idx2(n + 1, vector<int>(m + 1));for (int i = 1; i <= n; ++ i)for (int j = 1; j <= m; ++ j)   cin >> g[i][j];string s1, s2;int i = 1, j = 1, dir = 1, cnt = 0;while (i <= n){s1 += g[i][j], pos1[g[i][j] - 'a'].insert(cnt);idx1[i][j] = cnt ++ ;j += dir;if (j == m + 1) j = m, i ++ , dir *= -1;if (j == 0) j = 1, i ++, dir *= -1;}i = 1, j = 1, dir = 1, cnt = 0;while (j <= m){s2 += g[i][j], pos2[g[i][j] - 'a'].insert(cnt);idx2[i][j] = cnt ++ ;i += dir;if (i == n + 1) i = n, j ++ , dir *= -1;if (i == 0) i = 1, j ++ , dir *= -1;}int Q; cin >> Q;while (Q --){int t, x, y; cin >> t >> x >> y;if (t == 1){char c; cin >> c;pos1[s1[idx1[x][y]] - 'a'].erase(idx1[x][y]);pos2[s2[idx2[x][y]] - 'a'].erase(idx2[x][y]);            s1[idx1[x][y]] = c;s2[idx2[x][y]] = c;pos1[c - 'a'].insert(idx1[x][y]);pos2[c - 'a'].insert(idx2[x][y]);}else if (t == 2){int c = s1[idx1[x][y]] - 'a';int ans = inf;for (int i = 0; i < 26; ++ i)if (i != c){auto it = pos1[i].lower_bound(idx1[x][y]);if (it != pos1[i].end())ans = min(ans, *it);else ans = min(ans, n * m);}cout << ans - idx1[x][y] << "\n";}else{int c = s2[idx2[x][y]] - 'a';int ans = inf;for (int i = 0; i < 26; ++ i)if (i != c){auto it = pos2[i].lower_bound(idx2[x][y]);if (it != pos2[i].end())ans = min(ans, *it);else ans = min(ans, n * m);}cout << ans - idx2[x][y]  << "\n";}}
}int main()
{ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);solve();return 0;
}

F-小天的 A+B(结论题)

F-小天的 A+B_牛客小白月赛83 (nowcoder.com)
image.png

考虑每次操作的特殊性与 a i a_i ai的数据范围,对于一个长度为32的序列,假设经过运算的答案为ans,那么
a n s = m a x ( 2 30 a l , 2 30 a l + 1 , 2 29 a l + 2 , 2 28 a l + 3 , . . . , 2 1 a r − 1 , 2 0 a r ) ans=max(2^{30}a_l,2^{30}a_{l+1}, 2^{29}a_{l+2},2^{28}a_{l+3},...,2^1a_{r-1},2^0a_r) ans=max(230al,230al+1,229al+2,228al+3,...,21ar1,20ar)
每个 a i a_i ai之前都乘上了一个系数,并且这个系数随着序列长度的增大而增大,当序列长度为32时,前两个数的系数已经达到 2 30 2^{30} 230。由于 a i a_i ai的最大值为1e9,而 2 30 > 1 e 9 2^{30}>1e9 230>1e9,所以ans一定大于这个序列之后( a r a_r ar之后)的数。总结下,若区间[l, r]的前32个数中,存在一个正数,那么ans就是答案
若前32个数中不存在正数,但存在0,那么0就是答案
若前32个数中既不存在正数也不存在0,由于负数乘2会越来越小,所以需要在[l, r]区间的后32数中求ans

实现起来的细节还是很多的:

#include <bits/stdc++.h>
using namespace std;typedef long long LL;
const int mod9 = 998244353;
const int N = 1e6 + 10;
LL a[N], b[N];
set<int> pos, zr;LL f(int st, int l, int r)
{LL ans = (st == l ? 1 : 2) * a[st];int pos = st;while (pos + 1 <= r && pos - st <= 30)ans = 2 * max(ans, a[++ pos]);ans %= mod9;ans = ans * b[r - pos] % mod9;return (ans % mod9 + mod9) % mod9;
}void solve()
{int n, m; cin >> n >> m; b[0] = 1;for (int i = 1; i <= 1000000; ++ i)b[i] = b[i - 1] * 2 % mod9;for (int i = 1; i <= n; ++ i) {cin >> a[i];if (a[i] == 0) zr.insert(i);else if (a[i] > 0) pos.insert(i);}while (m --){int t; cin >> t;if (t == 1){int x, v; cin >> x >> v;if (a[x] == 0) zr.erase(x);else if (a[x] > 0) pos.erase(x);a[x] += v;if (a[x] == 0) zr.insert(x);else if (a[x] > 0) pos.insert(x);}else{int l, r; cin >> l >> r;auto it = pos.lower_bound(l);if (it != pos.end() && *it <= r){cout << f(*it, l, r) << "\n";continue;}it = zr.lower_bound(l);if (it != zr.end() && *it <= r){cout << "0\n";continue;}cout << f(max(l, r - 30), l, r) << "\n";}}
}int main()
{ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);solve();return 0;
}

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

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

相关文章

举个栗子!Tableau 技巧(261):自由切换图表的背景颜色

数据粉反馈了一个有趣的需求&#xff1a;Tableau 图表的背景颜色可以设置多个&#xff0c;然后按需切换么&#xff1f; 我们知道&#xff0c;图表的背景颜色对于可视化分析呈现来说非常重要。大部分情况下&#xff0c;我们会固定使用一种背景色。 如果确实需要切换图表背景颜…

K8s内容器拓扑图工具

1.背景&#xff1a;随着线上容器越来越多&#xff0c;需要一个可视化的方式展示各个容器之间的拓扑图。 2.需求&#xff1a;轻量级&#xff0c;部署方便。 3.部署 helm repo add groundcover https://helm.groundcover.com/ helm repo update helm install caretta --namespa…

代码随想录算法训练营第二十天 | 二叉搜索树

目录 力扣题目 力扣题目记录 654.最大二叉树 617.合并二叉树 用值 用指针 700.二叉搜索树中的搜索 递归 迭代 98.验证二叉搜索树 总结 力扣题目 用时&#xff1a;2h 1、654.最大二叉树 2、617.合并二叉树 3、700.二叉搜索树中的搜索 4、98.验证二叉搜索树 力扣…

JupyterNotebook VS JupyterLab 如果jupyter安装成功,点击jupyterlab即可进入lab环境

简介 JupyterNotebook 是一个款以网页为基础的交互计算环境&#xff0c;可以创建Jupyter的文档&#xff0c;支持多种语言&#xff0c;包括Python, Julia, R等等。一般来说&#xff0c;如果是使用R语言的话&#xff0c;使用Rstudio居多&#xff0c;使用Python的话&#xff0c;使…

如何快速优化几千万数据量的订单表

前言 为了保证有一个更健康的身体&#xff0c;所以慢慢降低了更新频率&#xff0c;在有了更多休息时间的前提下&#xff0c;思考了一下接下来准备分享的一些内容。 决定在更新一些技术干货的同时&#xff0c;会穿插一些架构知识&#xff0c;放在单独的专栏里面&#xff0c;希…

鸿蒙Js实战,计算器功能开发

场景&#xff1a; 通过动态设置按钮组件button实现计算器的键盘&#xff0c;通过文本text显示计算的表达书&#xff0c;可以计算&#xff0c;-&#xff0c;*&#xff0c;/&#xff0c;可以一个一个移除&#xff0c;可以重置 等。 下面我们开始今天的文章&#xff0c;还是老规…

【网络安全】-Linux操作系统基础

文章目录 Linux操作系统目录结构Linux命令格式Linux文件和目录操作命令Linux用户和用户组操作命令Linux查看和操作文件内容命令Linux文件压缩和解压缩命令Linux网络管理命令Linux磁盘管理和系统状态命令Linux安全加固总结 Linux是一个强大的操作系统&#xff0c;广泛用于服务器…

HarmonyOS 4应用开发:1.从环境搭建到Hello World

在踏上HarmonyOS应用开发之旅之前&#xff0c;需要进行一些必要的准备工作。首先&#xff0c;你需要下载并安装DevEco Studio&#xff0c;并进行相应的环境配置。 一、下载和安装DevEco Studio 前往DevEco Studio官方的下载地址&#xff0c;点击“立即下载”跳转至下载页面。…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)控件的部分公共属性和事件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;控件的部分公共属性和事件 一、操作环境 操作系统: Windows 10 专业版 IDE:DevEco Studio 3.1 SDK:HarmonyOS 3.1 二、公共属性 常用的公共属性有&#xff1a; 宽(with)、高(height)、…

深度学习记录--随机初始化

权重 权重&#xff0c;指的是变量系数w&#xff0c;决定了变量的变化率 它会改变dw&#xff0c;进而改变下一轮的w(改变更新) 神经网络的权重 对于神经网络(含隐藏层) 由于权重的对称性&#xff0c;我们的隐层的神经单元输出始终不变&#xff0c;出现隐藏神经元的对称性 …

WPF 显示PDF、PDF转成图片

1.NuGet 安装 O2S.Components.PDFView4NET.WPF 2.添加组件 工具箱中&#xff0c;空白处 右键&#xff0c;选择项 WPF组件 界面&#xff0c;选择NuGet安装库对面路径下的 O2S.Components.PDFView4NET.WPF.dll 3.引入组件命名空间&#xff0c;并使用 <Windowxmlns"htt…

antd-table:通过rowClassName实现斑马条纹样式+通过rowSelection实现单选功能效果——基础积累

斑马条纹 对于element-ui是有个stripe斑马条纹的属性的&#xff0c;最终呈现的效果如下&#xff1a; antd-table中是没有这个属性的&#xff0c;但是可以通过rowClassName&#xff1a;可以给对应行添加指定类名。 实现方法&#xff1a; <a-table:rowClassName"getRo…

每日一练2023.12.18——天梯赛的善良【PTA】

题目链接&#xff1a;L1-079 天梯赛的善良 题目要求&#xff1a; 天梯赛是个善良的比赛。善良的命题组希望将题目难度控制在一个范围内&#xff0c;使得每个参赛的学生都有能做出来的题目&#xff0c;并且最厉害的学生也要非常努力才有可能得到高分。 于是命题组首先将编程能…

Qt for Android设置安卓程序默认横屏+全屏

我的qt版本是5.14.1&#xff0c;网上查到的方法是&#xff0c;把编译出的build文件夹中的AndroidManifest.xml文件复制出来然后修改&#xff0c;然后把修改后的xml文件加入pro文件&#xff0c;语法为ANDROID_PACKAGE_SOURCE_DIR $$PWD/AndroidManifest.xml&#xff08;具体&am…

vue3如何动态添加组件到dom中(jsx,h(),render)

背景&#xff0c;在写自定义指令的时候遇见&#xff0c;需要把svg图标组件动态添加到div中&#xff0c;然后把方法绑定到图标上 1、创建jsx import IconSvg from "/components/IconSvg/IconSvg.vue";const renderDom () > {return (<IconSvg class"ico…

【算法与数据结构】122、LeetCode买卖股票的最佳时机 II

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;股票要想盈利&#xff0c;必须低买高卖。在第N天买入&#xff0c;然后在第M天卖出&#xff0c;所获的利…

Docker使用4-Persist the DB

写在前面 主题是Persist the DB&#xff0c;这里是链接。本文主要学习如何持久化容器中的数据。 实践 使用docker运行一个随机生成1-10000的数的命令。下面是两个命令用&&合并在一起&#xff0c;第一个命令是生成随机数并输出到data.txt&#xff0c;后面的命令是保持…

echarts 饼图3样式

父组件&#xff1a; <pieChartNormal :opt"contractStatics" style"width: 100%;height: 100%;" />import pieChartNormal from "./components/pieChartNormal";data() {return {contractStatics: {seriesData: [{name: 技术服务类,value:…

优思学院|有了人工智能,质检员快将失业了吗?

从前&#xff0c;质检员是执着于质量的守护者。他们拥有工作轻松、压力小、时间自由的优势&#xff0c;然而&#xff0c;这种优越感背后隐藏着容易得罪人、进步空间受限、上升机会有限的挑战&#xff0c;近年&#xff0c;随着人工智能、自动化等理念推陈出新&#xff0c;许多传…

AI浪潮下,大模型如何在音视频领域运用与实践?

视频云大模型算法「方法论」。 刘国栋&#xff5c;演讲者 在AI技术发展如火如荼的当下&#xff0c;大模型的运用与实践在各行各业以千姿百态的形式展开。音视频技术在多场景、多行业的应用中&#xff0c;对于智能化和效果性能的体验优化有较为极致的要求。如何运用好人工智能提…