牛客周赛 Round 14 题解报告 | 珂学家 | 环形模拟 + 滑窗前缀和二分 + 数学


前言

alt


整体评价

这场牛客周赛很特别,没有一题是水题(签到),也没真正意义上的压轴题。

牛客周赛还是注重数学,B,D是数学题,A是模拟题,C的解法偏多,滑窗/26组前缀和&二分皆可。


A. 小红的环形字符串

如果没有环形,那这题单纯使用一个 stack 就可以解决,就是括号匹配问题一样

那如果是环形结构呢?

其实这题有一个性质

x…AAA…y

中间的3个A,如果第一个和第二个匹配,还是第二个和第三个匹配,都不会影响结果

同理在环形链接处,也满足相似的结论。


核心结论:

根据等价原理,合并操作的顺序,并不影响最终结果

可以引入双端队列

先把双端队列当栈使用

最后比较双端队列的头和尾,进行抵消

import java.io.*;
import java.util.*;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(new BufferedInputStream(System.in));int n = sc.nextInt();char[] str = sc.next().toCharArray();// 等价原理// 1. 先当stack使用int ans = 0;Deque<Character> deq = new ArrayDeque<>();for (int i = 0; i < n; i++) {char c = str[i];if (!deq.isEmpty() && deq.peekLast() == c) {ans += 2;deq.pollLast();} else {deq.addLast(c);}}// 2. 双端队列,合并头和尾while (deq.size() >= 2 && deq.peekFirst() == deq.peekLast().charValue()) {ans += 2;deq.pollFirst();deq.pollLast();}System.out.println(ans);}}

B. 小红的乘除变换

这题的5和6其实很特别互质

可以从因子5,6的角度切入

x的5,6的因子个数nx5, nx6

y的5,6的因子个数ny5, ny6

令tx为x去除5,6因子后的数,ty为y去除5,6因子后的数

如果 tx != ty, 则 x 不可能转化为 y

5是乘,6是除,那 nx5 > ny5 || nx6 < ny6, 也不存在解

最后的操作数为 ny5 - nx5 + nx6 - ny6

import java.io.*;
import java.util.*;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(new BufferedInputStream(System.in));int t = sc.nextInt();while (t-- > 0) {long x = sc.nextLong();long y = sc.nextLong();int ny5 = 0, ny6 = 0;while (y > 0 && y % 5 == 0) { y /= 5; ny5++; }while (y > 0 && y % 6 == 0) { y /= 6; ny6++; }int nx5 = 0, nx6 = 0;while (x > 0 && x % 5 == 0) { x /= 5; nx5++; }while (x > 0 && x % 6 == 0) { x /= 6; nx6++; }if (x != y || nx5 > ny5 || nx6 < ny6) {System.out.println(-1);} else {System.out.println(ny5 - nx5 + nx6 - ny6);}}}}

C. 小红的子串

按照定义,连续区间 [a, b]其不同的字符数 在 [l, r]之间,被小红心中的意中人。

求这样的子区间总个数 ?

因为字符串的长度为 2 × 1 0 5 2\times 10^5 2×105, 因此没法从枚举左右两端点入手。

大致有两种思路

  • 滑窗
  • 枚举左(右)端点, 然后二分求右(左)边界

滑窗

滑窗可以用三指针,也可以用双指针

三指针,枚举右(左)端点, 然后滑窗维护[l, r]不同字符种类数的边界p1, p2, 结果为

ans += abs(p2 - p1)

双指针,定义f(x)为种类数 >= x的方案总数

res = f(l) - f(r + 1)

import java.io.*;
import java.util.*;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(new BufferedInputStream(System.in));int n = sc.nextInt();int l = sc.nextInt(), r = sc.nextInt();char[] str = sc.next().toCharArray();Map<Integer, Integer> hash1 = new HashMap<>();Map<Integer, Integer> hash2 = new HashMap<>();long ans = 0;int p1 = 0, p2 = 0;for (int i = 0; i < n; i++) {int v = str[i] - 'a';hash1.merge(v, 1, Integer::sum);hash2.merge(v, 1, Integer::sum);// 维护有r种不同字符的边界, > rwhile (p1 <= i && hash1.size() > r) {hash1.computeIfPresent(str[p1] - 'a', (a, b) -> b > 1 ? b - 1 : null);p1++;}// 维护有l种不同字符的边界, >=lwhile (p2 <= i && hash2.size() >= l) {hash2.computeIfPresent(str[p2] - 'a', (a, b) -> b > 1 ? b - 1 : null);p2++;}ans += (p2 - p1);}System.out.println(ans);}}
import java.io.*;
import java.util.*;public class Main {/*双指针,定义f(x)为种类数 >= x的方案总数res = f(l) - f(r + 1) */static long solve(char[] str, int x) {Map<Integer, Integer> hash = new HashMap<>();long ans = 0;int j = 0;for (int i = 0; i < str.length; i++) {int v = str[i] - 'a';hash.merge(v, 1, Integer::sum);while (j <= i && hash.size() >= x) {hash.computeIfPresent(str[j] - 'a', (a, b) -> b > 1 ? b - 1 : null);j++;}ans += j;}return ans;}public static void main(String[] args) {Scanner sc = new Scanner(new BufferedInputStream(System.in));int n = sc.nextInt();int l = sc.nextInt(), r = sc.nextInt();char[] str = sc.next().toCharArray();System.out.println(solve(str, l) - solve(str, r + 1));}}

前缀和&二分

字符种类最多是26,是有限可枚举

因此这也是一个切入点

构建26 slots的前缀和

然后求二分求 [l, r]的两个边界

import java.io.*;
import java.util.*;public class Main {static int binarySearch(int[][] pre, int e, int x) {int l = 0, r = e;while (l <= r) {int m = l + (r - l) / 2;// 统计不同字符种类个数int cnt = 0;for (int i = 0; i < 26; i++) {if (pre[i][e + 1] - pre[i][m] > 0) cnt++;}// cnt >= x 是 check核心逻辑if (cnt >= x) {l = m + 1;} else {r = m - 1;}}return r;}public static void main(String[] args) {Scanner sc = new Scanner(new BufferedInputStream(System.in));int n = sc.nextInt();int l = sc.nextInt(), r = sc.nextInt();char[] str = sc.next().toCharArray();int[][] pre = new int[26][n + 1];// 构建26个前缀和for (int i = 0; i < n; i++) {for (int j = 0; j < 26; j++) {pre[j][i + 1] = pre[j][i] + (str[i] - 'a' == j ? 1 : 0);}}long ans = 0;for (int i = 0; i < n; i++) {ans += binarySearch(pre, i, l) - binarySearch(pre, i, r + 1);}System.out.println(ans);}}

D. 回文权值和

算一道高中数学题吧

就是求 2 6 n 26^n 26n的串中,连续长度为3的回文子串总数有多少个

假设(i, i+1, i+2),其构成回文的种类为 26 × 26 = 676 26\times26=676 26×26=676个,那在 2 6 n 26^n 26n种可能字符串中。

一共出现为 2 6 n − 3 26^{n-3} 26n3

同时,这样的三元组,在n长的字符串中,一共可以枚举 n − 2 n - 2 n2

综合得

r e s = 676 × ( n − 2 ) × 2 6 n − 3 res = 676 \times (n-2) \times 26^{n-3} res=676×(n2)×26n3

676 * (n - 2) * 26^(n-3)

考察了快速幂这个知识点

import java.io.*;
import java.util.*;public class Main {public static long ksm(long b, long v, long mod) {long r = 1l;b = b % mod;while (v > 0) {if (v % 2 == 1) r = r * b % mod;b = b * b % mod;v /= 2;}return r;}public static void main(String[] args) {Scanner sc = new Scanner(new BufferedInputStream(System.in));long n = sc.nextLong();// n < 3没有解if (n < 3) {System.out.println(0);return;}long mod = (long)1e9 + 7;long res = 676l * ksm(26, n - 3, mod) % mod * ((n - 2) % mod) % mod;System.out.println(res);}}

写在最后

alt

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

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

相关文章

欧科云链与《警察技术》联合发布技术专题.pdf

欧科云链受《警察技术》邀请&#xff0c;于第201期期刊正式刊登“区块链生态安全与虚拟货币犯罪治理”技术专题。欧科云链作为该技术专题主要作者&#xff0c;直接参与本次期刊2篇文章撰写&#xff0c;同时为多篇文章提供欧科云链的最新数据和研究成果。 《警察技术》期刊创办于…

深入Docker5:安装nginx部署完整项目

目录 准备 为什么要使用nginx mysql容器构建 1.删除容器 2.创建文件夹 3.上传配置文件 4.命令构建mysql容器 5.进入mysql容器&#xff0c;授予root所有权限 6.在mysql中用命令运行sql文件 7.创建指定数据库shop 8.执行指定的sql文件 nginx安装与部署 1.拉取镜像 2…

C++ 之路如逆水行舟 不进则退

C 核心编程 内存分区模型 C 程序在执行时&#xff0c;将内存大方向划分为 4 个区域 代码区&#xff1a;存放函数体的二进制代码&#xff0c;由操作系统进行管理的 全局区&#xff1a;存放全局变量和静态变量以及常量 栈区&#xff1a;由编译器自动分配释放 , 存放函数的参数…

15、注册表永久关闭Citrix云桌面UAC功能

一、说明 我们经常使用Citrix云桌面时候遇到打开软件会弹出一个输密码的界面&#xff0c;这个其实是UAC&#xff0c;此次我们主要使用注册表方式彻底关闭。 二、注册表方式 打开路径&#xff1a;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Syst…

新版AndroidStudio dependencyResolutionManagement出错

在新版AndroidStudio中想像使用4.2版本或者4.3版本的AndroidStudio来构造项目&#xff1f;那下面这些坑我们就需要来避免了&#xff0c;否则会出各种各样的问题。 一.我们先来看看新旧两个版本的不同。 1.jdk版本的不同 新版默认是jdk17 旧版默认是jdk8 所以在新版AndroidSt…

Mysql root 密码重置详解

文章目录 1 概述1.1 前言1.2 mysql 版本查询 2 windows 操作系统2.1 mysql 8 及以上版本2.1.1 关闭 mysql 服务2.1.2 通过无认证方式启动 mysql2.1.3 新开窗口&#xff0c;登录 mysql&#xff0c;重置密码 1 概述 1.1 前言 不同的操作系统&#xff08;如&#xff1a;windows、…

Unity 编辑器篇|(十)Handles (全面总结 | 建议收藏)

目录 1. 前言2 参数总览3 Handles两种使用方式3.1 基于Editor类的OnSceneGUI3.2 基于EditorWindow 4 Handles绘制4.1 Draw&#xff1a;绘制元几何体(点、线、面)4.1.1 抗锯齿&#xff1a; DrawAAPolyLine 、 DrawAAConvexPolygon4.1.2 绘制实线: DrawLine 、 DrawLines 、DrawP…

Python基础第一篇(Python概念介绍)

文章目录 一、前言&#xff1a;二、第一个Python程序三&#xff0c;理解Python的解释器四&#xff0c;Python解释器的使用五&#xff0c;Python开发环境 一、前言&#xff1a; 欢迎来到我们的Python学习专栏。在这里&#xff0c;我们将一起探索Python这门强大、灵活、易于学习…

electron+vite+vue3 快速入门教程

文章目录 前言一、electron是什么&#xff1f;二、electron 进程模型1.主进程2.渲染进程3.预加载脚本4.进程通信4.1 sendon&#xff08;单向&#xff09;4.2 invokehandle (双向)4.3 主进程向渲染进程发送事件 三、窗口创建与应用事件四、技术栈和构建工具五、electron-vite安装…

龙年-微信定制红包封面,送一波

龙年新年马上就要来临了&#xff0c;我定制两款红包封面&#xff0c;送给大家。这次是借助AI的能力&#xff0c;自己独立完成&#xff0c;这大概就是这波AI浪潮的魅力&#xff0c;人人皆可参与。 另外&#xff0c;微信平台也给我推送了自己的公众号创作回顾&#xff0c;没想到居…

Unity常用的优化技巧集锦

Unity性能优化是面试的时候经常被问道的一些内容&#xff0c;今天给大家分享一些常用的Unity的优化技巧和思路&#xff0c;方便大家遇到问题时候参考与学习。 对啦&#xff01;这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小白&#xff0c;也有一些正在从事游…

RabbitMQ 部署与配置[CentOS7]

# RabbitMQ,Erlang 版本包对应 https://rabbitmq.com/which-erlang.html#eol-seriescd /usr/local/src# Erlang下载 # https://github.com/rabbitmq/erlang-rpm/releases https://github.com/rabbitmq/erlang-rpm/releases/download/v23.3.4.5/erlang-23.3.4.5-1.el7.x86_64.rp…