2023年第6届传智杯省赛第二场复赛 解题报告 | 珂学家


前言

因为OJ的承办方是牛客,除了初赛用的原题有点争议外,复赛用的是原创的新题(点赞)。

说真的,这个难度,超过我的想象,打得非常的吃力。

我其实总共打了两场初赛,一场复赛,外加VP一场复赛,没有一场是AK的,很惭愧。

第二场复赛,T3卡了下,然后T4头痛,T5没找到线索,倒是T6一眼题,最后关头磨出了T4,真的太不容易,感谢自己的坚持。


A.

思路: 模拟

标准的签到题

import java.io.BufferedInputStream;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        // 需要替换为快读
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        int n = sc.nextInt(), x = sc.nextInt();
        int res = 0;
        int pre = 0;
        for (int i = 0; i < n; i++) {
            int v = sc.nextInt();
            if (i > 0 && pre < x && v >= x) {
                res++;
            }
            pre = v;
        }
        System.out.println(res);
    }
    
}

B.

思路: 贪心

尽量挑选频数多的字母,尾巴需要额外处理下

因为 x + y = a + b , x < a < b < y x+y=a+b, x<a<b<y x+y=a+b,x<a<b<y
进而 x 2 + y 2 > a 2 + b 2 x^2 + y^2 > a^2 + b^2 x2+y2>a2+b2

所以大的就让它越大,这样整体就越大

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Scanner;
import java.util.StringTokenizer;

public class Main {

    public static void main(String[] args) {
        // 需要替换为快读
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        int n = sc.nextInt(), k = sc.nextInt();
        int[] hash = new int[26];

        char[] str = sc.next().toCharArray();
        for (int i = 0; i < str.length; i++) {
            hash[str[i] - 'a']++;
        }

        long res = 0;
        Arrays.sort(hash);
        for (int i = 0; k > 0 && i < 26; i++) {
            int d = Math.min(k, hash[i]);
            res += (long)d * d;
            k -= d;
        }
        System.out.println(res);
    }

}


C.

思路: 枚举

找到所有不满足要求的相邻点

然后枚举被交换的位置,如果操作之后,会消灭点不满足要求的点,那么该点就是解。

这边有个结论
如果不满足的相邻点超过 2 个,那一定无解 如果不满足的相邻点超过2个,那一定无解 如果不满足的相邻点超过2个,那一定无解

这题挺容易错的,出的蛮好,很羡慕哪些秒杀这题的同学。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.TreeSet;

public class Main {

    public static void main(String[] args) {

        // 预处理质数
        int MN = 2 * 10_0000;
        boolean[] vis = new boolean[MN + 1];
        vis[1] = false;
        for (int i = 2; i <= MN; i++) {
            if (!vis[i]) {
                if (i > MN / i) continue;
                for (int j = i * i; j <= MN; j+=i) {
                    vis[j] = true;
                }
            }
        }

        AReader sc = new AReader();
        int n = sc.nextInt();

        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = sc.nextInt();
        }

        // 收集所有的坏点
        List<Integer> bads = new ArrayList<>();
        for (int i = 0; i < n - 1; i++) {
            if (vis[arr[i] + arr[i + 1]]) bads.add(i);
        }
        if (bads.size() > 2) {
            System.out.println(-1);
        } else {
            TreeSet<Integer> ans = new TreeSet<>();
            for (int v: bads) ans.add(v);

            // 模拟统计满足要求的点
            int res = -1;
            int exp = 0;
            for (int i = 0; i < n - 1; i++) {
                TreeSet<Integer> tmp = new TreeSet<>(ans);
                if (i > 0 && !vis[arr[i + 1] + arr[i - 1]]) tmp.remove(i - 1);
                if (i + 2 < n && !vis[arr[i + 2] + arr[i]]) tmp.remove(i + 1);
                if (tmp.size() == 0) {
                    res = i + 1;
                    exp++;
                }
            }

            System.out.println(exp == 1 ? res : -1);
        }
    }

    static
    class AReader {
        private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        private StringTokenizer tokenizer = new StringTokenizer("");
        private String innerNextLine() {
            try {
                return reader.readLine();
            } catch (IOException ex) {
                return null;
            }
        }
        public boolean hasNext() {
            while (!tokenizer.hasMoreTokens()) {
                String nextLine = innerNextLine();
                if (nextLine == null) {
                    return false;
                }
                tokenizer = new StringTokenizer(nextLine);
            }
            return true;
        }
        public String nextLine() {
            tokenizer = new StringTokenizer("");
            return innerNextLine();
        }
        public String next() {
            hasNext();
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }
    }

}


D.

思路:枚举

有一个特例,就是重合的点数刚好为 n 有一个特例,就是重合的点数刚好为n 有一个特例,就是重合的点数刚好为n

枚举两点(不重合)构建的一条直线,然后利用叉乘计算

  • 直线上
  • 直线左侧
  • 直线右侧
    的点个数和分布,满足均分,就是所求的结果

是一道蛮数学化的题

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

public class D {

    static class Key {
        int x, y;
        public Key(int x, int y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public int hashCode() {
            return x * 1331 + y;
        }

        @Override
        public boolean equals(Object obj) {
            Key d = (Key)obj;
            return x == d.x && y == d.y;
        }
    }

    static class Line {
        int x, y;
        int x2, y2;
        int dx, dy;
        public Line(int x1, int y1, int x2, int y2) {
            // 直线的表达
            this.x = x1; this.y = y1;
            this.x2 = x2; this.y2 = y2;
            this.dx = x2 - x1;
            this.dy = y2 - y1;

            if (this.dx < 0) {
                this.dx = -this.dx;
                this.dy = -this.dy;
            }
        }

        boolean inLine(int px, int py) {
            int tx = px - x;
            int ty = py - y;

            if (tx < 0) {
                tx = -tx;
                ty = -ty;
            }

            if (dx == 0) {
                return tx == 0;
            }
            if (dy == 0) {
                return ty == 0;
            }
            return (long)dx * ty == (long)dy * tx;
        }

        boolean isLeft(int px, int py) {
            int dx1 = px - x, dy1 = py - y;
            int dx2 = x2 - x, dy2 = y2 - y;
            return dx1 * dy2 - dx2 * dy1 > 0;
        }

        long[] expr() {
            // y = dy/dx * x + c
            // c => y0 - dy/dx * x0
            if (dx == 0) {
                return new long[] {1, 0, -x};
            }
            if (dy == 0) {
                return new long[] {0, 1, -y};
            }
            return new long[] {dy, -dx, (long)y * dx - (long)dy * x};
        }

    }

    public static void main(String[] args) {

        AReader sc = new AReader();

        Map<Key, Integer> hash = new HashMap<>();
        int n = sc.nextInt();
        int m = 3 * n;
        int[][] ps = new int[m][2];
        for (int i = 0; i < m; i++) {
            ps[i][0] = sc.nextInt();
            ps[i][1] = sc.nextInt();
            hash.merge(new Key(ps[i][0], ps[i][1]), 1, Integer::sum);
        }

        Line ans = null;
        boolean found = false;
        // 这边进行枚举
        for (int i = 0; !found && i < m; i++) {
            for (int j = i + 1; !found && j < m; j++) {
                if (ps[i][0] == ps[j][0] && ps[i][1] == ps[j][1]) continue;

                Line line = new Line(ps[i][0], ps[i][1], ps[j][0], ps[j][1]);
                int n0 = 2, n1 = 0, n2 = 0;
                for (int k = 0; k < m; k++) {
                    if (k == i || k == j) continue;
                    if (line.inLine(ps[k][0], ps[k][1])) n0++;
                    else if (line.isLeft(ps[k][0], ps[k][1])) n1++;
                    else n2++;
                }
                if (n0 == n1 && n1 == n2) {
                    found = true;
                    ans = line;
                }
            }
        }

        if (ans == null) {
            // 存在一个特例
            for (Map.Entry<Key, Integer> kv : hash.entrySet()) {
                if (kv.getValue() == n) {
                    int sx = kv.getKey().x;
                    int sy = kv.getKey().y;
                    // 黑洞点
                    for (int i = -2000; i <= 2000; i++) {
                        Line tmp = new Line(sx, sy, sx + 1, sy + i);

                        int left = 0, right = 0;
                        for (int k = 0; k < m; k++) {
                            if (ps[k][0] == sx && ps[k][1] == sy) continue;
                            if (tmp.isLeft(ps[k][0], ps[k][1])) left++;
                            else right++;
                        }
                        if (left == right) {
                            ans = tmp;
                            break;
                        }
                        left = 0;
                        right = 0;
                        tmp = new Line(sx, sy, sx + i, sy + 1);
                        for (int k = 0; k < m; k++) {
                            if (ps[k][0] == sx && ps[k][1] == sy) continue;
                            if (tmp.isLeft(ps[k][0], ps[k][1])) left++;
                            else right++;
                        }
                        if (left == right) {
                            ans = tmp;
                            break;
                        }
                    }
                    break;
                }
            }
        }
        if (ans == null) {
            System.out.println(-1);
        } else {
            long[] cur = ans.expr();
            System.out.println(cur[0] + " " + cur[1] + " " + cur[2]);
        }

    }

    static
    class AReader {
        private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        private StringTokenizer tokenizer = new StringTokenizer("");
        private String innerNextLine() {
            try {
                return reader.readLine();
            } catch (IOException ex) {
                return null;
            }
        }
        public boolean hasNext() {
            while (!tokenizer.hasMoreTokens()) {
                String nextLine = innerNextLine();
                if (nextLine == null) {
                    return false;
                }
                tokenizer = new StringTokenizer(nextLine);
            }
            return true;
        }
        public String nextLine() {
            tokenizer = new StringTokenizer("");
            return innerNextLine();
        }
        public String next() {
            hasNext();
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }
    }

}


E.

完全没思路,蒙了


F.

思路:字符串hash + 线段树

综合题,但是比较简单

这边可以借助双hash,来构建,避免碰撞带来的WA.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class F {

    static long mod = (long)1e9 + 7;
    static long p1 = 13;
    static long p2 = 17;

    static final int MZ = 100_00000;
    static long[] dp1 = new long[MZ + 1];
    static long[] dp2 = new long[MZ + 1];

    public static void setUp() {
        dp1[0] = dp2[0] = 1;
        for (int i = 1; i < MZ; i++) {
            dp1[i] = dp1[i - 1] * p1 % mod;
            dp2[i] = dp2[i - 1] * p2 % mod;
        }
    }

    // 线段树
    static class SegTree {
        int l, r;
        SegTree left, right;
        int v;
        long h1, h2;

        public SegTree(char[] str, int l, int r) {
            this.l = l;
            this.r = r;
            if (l == r) {
                this.v = str[l] - 'a';
                h1 = v % mod;
                h2 = v % mod;
                return;
            } else {
                int m = l + (r - l) / 2;
                left = new SegTree(str, l, m);
                right = new SegTree(str, m + 1, r);
                pushup();
            }
        }

        public void update(int p, char c) {
            if (isLeaf()) {
                this.v = c - 'a';
                h1 = v % mod;
                h2 = v % mod;
                return;
            }

            int m = l + (r - l) / 2;
            if (p <= m) {
                this.left.update(p, c);
            } else {
                this.right.update(p, c);
            }
            pushup();
        }

        long query1(int ql, int qr) {
            if (isLeaf()) {
                return this.h1;
            }
            if (ql <= l && qr >= r) {
                return this.h1;
            }

            int m = l + (r - l) / 2;
            long lh = 0;
            if (ql <= m) {
                lh = this.left.query1(ql, Math.min(m, qr));
            }
            long rh = 0;
            if (qr > m) {
                rh = this.right.query1(Math.max(m +1, ql), qr);
            }

            int d = Math.max(0, qr - m);
            return (lh * dp1[d] + rh) % mod;
        }

        long query2(int ql, int qr) {
            if (isLeaf()) {
                return this.h2;
            }
            if (ql <= l && qr >= r) {
                return this.h2;
            }

            int m = l + (r - l) / 2;
            long lh = 0;
            if (ql <= m) {
                lh = this.left.query2(ql, Math.min(m, qr));
            }
            long rh = 0;
            if (qr > m) {
                rh = this.right.query2(Math.max(m +1, ql), qr);
            }

            int d = Math.max(0, qr - m);
            return (lh * dp2[d] + rh) % mod;
        }

        public void pushup() {
            int m = l + (r - l) / 2;
            h1 = (left.h1 * dp1[r - m] % mod + right.h1) % mod;
            h2 = (left.h2 * dp2[r - m] % mod + right.h2) % mod;
        }

        boolean isLeaf() {return l== r;}

    }

    public static void main(String[] args) {

        setUp();

        AReader sc = new AReader();

        int n = sc.nextInt();
        int q = sc.nextInt();
        char[] str = sc.next().toCharArray();

        SegTree root = new SegTree(str, 0, n - 1);

        for (int i = 0; i < q; i++) {
            int op = sc.nextInt();
            if (op == 1) {
                int x = sc.nextInt() - 1;
                char c = sc.next().charAt(0);
                root.update(x, c);
            } else if (op == 2) {
                int l1 = sc.nextInt() - 1, r1 = sc.nextInt() - 1;
                int l2 = sc.nextInt() - 1, r2 = sc.nextInt() - 1;
                if (root.query1(l1, r1) == root.query1(l2, r2) && root.query2(l1, r1) == root.query2(l2, r2)) {
                    System.out.println("Yes");
                } else {
                    System.out.println("No");
                }
            }
        }
    }

    static
    class AReader {
        private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        private StringTokenizer tokenizer = new StringTokenizer("");
        private String innerNextLine() {
            try {
                return reader.readLine();
            } catch (IOException ex) {
                return null;
            }
        }
        public boolean hasNext() {
            while (!tokenizer.hasMoreTokens()) {
                String nextLine = innerNextLine();
                if (nextLine == null) {
                    return false;
                }
                tokenizer = new StringTokenizer(nextLine);
            }
            return true;
        }
        public String nextLine() {
            tokenizer = new StringTokenizer("");
            return innerNextLine();
        }
        public String next() {
            hasNext();
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }
    }

}

写在最后

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何用Excel制作一张能在网上浏览的动态数据报表

前言 如今各类BI产品大行其道&#xff0c;“数据可视化”成为一个热门词汇。相比价格高昂的各种BI软件&#xff0c;用Excel来制作动态报表就更加经济便捷。今天小编就将为大家介绍一下如何使用葡萄城公司的纯前端表格控件——SpreadJS来实现一个Excel动态报表&#xff1a; 实…

C语言中关于指针的理解

#include <stdio.h> int main() {int a11;int *p&a; //因为a是整型的&#xff0c;所以我们定义指针p的时候要和a的类型一样char b;char *pa&b; //同理&#xff0c;b是字符型&#xff0c;所以这里的pa也要用字符型return 0; }因为*p指向的是地址&…

高级RGA(二):父文档检索器

在我之前写的<<使用langchain与你自己的数据对话>>系列博客中&#xff0c;我们介绍了利用大型语言模型LLM来检索文档时的过程和步骤&#xff0c;如下图所示&#xff1a; 我们在检索文档之前&#xff0c;通常需要对文档进行切割&#xff0c;然后将其存入向量数据库如…

Seata源码——TCC模式总结

什么是TCC TCC 是分布式事务中的二阶段提交协议&#xff0c;它的全称为 Try-Confirm-Cancel&#xff0c;即资源预留&#xff08;Try&#xff09;、确认操作&#xff08;Confirm&#xff09;、取消操作&#xff08;Cancel&#xff09; TCC的步骤 1.Try&#xff1a;对业务资源…

米勒电容与米勒效应

米勒电容与米勒效应 米勒效应米勒效应的形成原理及分析米勒效应的危害和改进 米勒效应 Ciss CGE CGC 输入电容 Coss CGC CEC 输出电容 Crss CGC 米勒电容 下面我们以MOS中的米勒效应来展开说明&#xff1a; 米勒效应在MOS驱动中臭名昭著&#xff0c;它是由MOS管的米勒电容引发…

揭秘NCO:数字领域的音乐之旅

好的&#xff0c;让我们更详细地解析NCO的数学奥秘&#xff0c;深入探讨数字音乐的乐谱。在我们深入数学公式之前&#xff0c;让我们回顾一下&#xff0c;NCO就像是一位神奇的音符设计师&#xff0c;创造数字音乐的灵感源泉。 NCO&#xff1a;数字音符的魔法创造者 NCO&#x…

JavaEE:CAS详解

一.什么是CAS CAS: 全称 Compare and swap &#xff0c;字面意思 :” 比较并交换 “ &#xff0c;一个 CAS 涉及到以下操作&#xff1a; 我们假设内存中的原数据V&#xff0c;旧的预期值A&#xff0c;需要修改的新值B。 我们来进行操作&#xff1a; 1. 比较 V 和 A 是否相等。…

C语言中关于操作符的理解

本篇文章只会列出大家在生活中经常使用的操作符 算术操作符 在算数操作符中常用的有&#xff0c;&#xff0c;-&#xff0c;*&#xff0c;/&#xff0c;% &#xff0c;我们重点讲一讲 / (除) 和 % (模) " / "运算 #include <stdio.h>int main() {int a5/2;fl…

C/C++常见面试题(四)

C/C面试题集合四 目录 1、什么是C中的类&#xff1f;如何定义和实例化一个类&#xff1f; 2、请解释C中的继承和多态性。 3、什么是虚函数&#xff1f;为什么在基类中使用虚函数&#xff1f; 4、解释封装、继承和多态的概念&#xff0c;并提供相应的代码示例 5、如何处理内…

鸿蒙应用开发 常用组件与布局

简介 HarmonyOS ArkUI 提供了丰富多样的 UI 组件&#xff0c;您可以使用这些组件轻松地编写出更加丰富、漂亮的界面。在本篇 Codelab 中&#xff0c;您将通过一个简单的购物社交应用示例&#xff0c;学习如何使用常用的基础组件和容器组件。本示例主要包含&#xff1a;“登录”…

五、交换机基础配置实验

文章目录 实验内容实验拓扑配置交换机双工模式 实验内容 某公司刚成立&#xff0c;新组建网络&#xff0c;购置了 3 台交换机。其中 S1和 S2为接入层交换机&#xff0c;S3 为汇聚层交换机。现在网络管理员需要对3 台新交换机进行基本配置&#xff0c;保证交换机间的接口使用全…

Spring系列学习一、Spring框架的概论

Spring框架的概论 一、 Spring框架的起源与历史二、 Spring框架的核心理念与特点三、 Spring与其他框架的对比1、首先介绍下Spring与其平替的EJB的对比&#xff1a;2、接下来介绍下Spring与基于Java EE原生技术的对比3、Spring与Hibernate的对比4、Spring与Struts的对比 四、Sp…

Oracle研学-查询

学自B站黑马程序员 1.单表查询 //查询水表编号为 30408 的业主记录 select * from T_OWNERS where watermeter30408 //查询业主名称包含“刘”的业主记录 select * from t_owners where name like %刘% //查询业主名称包含“刘”的并且门牌号包含 5 的业主记录 select * from…

视频编辑与制作,添加视频封面的软件

如今&#xff0c;视频已经成为了我们生活中不可或缺的一部分&#xff0c;无论是社交媒体上的短视频&#xff0c;还是电影、电视剧&#xff0c;视频都以其独特的魅力吸引着我们的目光。而在这背后&#xff0c;视频剪辑软件功不可没。今天&#xff0c;我就为大家揭秘一款新一代的…

强化学习_06_pytorch-TD3实践(CarRacing-v2)

0、TD3算法原理简介 详见笔者前一篇实践强化学习_06_pytorch-TD3实践(BipedalWalkerHardcore-v3) 1、CarRacing环境观察及调整 Action SpaceBox([-1. 0. 0.], 1.0, (3,), float32)Observation SpaceBox(0, 255, (96, 96, 3), uint8) 动作空间是[-1~1, 0~1, 0~1]&#xff0c…

10 NAT网络地址转换

广域网技术 上面聊的内容都是内网的一些配置&#xff0c;但内网终将要访问外网的&#xff0c;我们需要怎么处理呢&#xff1f;一般使用HDLC&#xff08;高级数据链路控制协议&#xff09;或者PPP&#xff08;点对点协议&#xff09;。 使用PPP安全接入Internet PPP&#xff0…

Podman配置mongodb

文章目录 查询镜像拉取镜像查看镜像运行容器创建root用户 查询镜像 podman search mongo拉取镜像 podman pull docker.io/library/mongo查看镜像 podman images运行容器 podman run -d -p 27017:27017 --namemongodb-test docker.io/library/mongo创建root用户 podman exe…

详解现实世界资产(RWAs)

区块链中的现实世界资产&#xff08;RWAs&#xff09;是代表实际和传统金融资产的数字通证&#xff0c;如货币、大宗商品、股票和债券。 实际世界资产&#xff08;RWA&#xff09;的通证化是区块链行业中最大的市场机会之一&#xff0c;潜在市场规模可达数万万亿美元。理论上&…

12章总结

一.集合类概述 java.util包中提供了一些集合类&#xff0c;这些集合类又被称为容器。 集合类与数组的不同之处&#xff1a; 数组的长度是固定的&#xff0c;集合的长度是可变的&#xff1a;数组用来存放基本类型的数据&#xff0c;集合用来存放对象的引用。 常…

windows下使用vccode+cmake编译cuda程序

1、在vscode中安装Nsight Visual Studio Code Edition 在vscode中安装插件能够对cuda的代码进行语法检查 2、编写cuda程序 #include <iostream>__global__ void mykernelfunc(){}; int main() {mykernelfunc<<<1,1>>>();std::cout << "hel…