【蓝桥杯】每日一题冲刺国赛

今日学习📃

🎋1、巧拼扑克牌

🎃2、质数拆分

🖼️3、日志统计

🎄4、递增三元组

🎍5、外卖店优先级

 🎋1、巧拼扑克牌

🎯题目描述

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

小明刚上小学,学会了第一个扑克牌“魔术”,到处给人表演。魔术的内容是这样的:

他手里握着一叠扑克牌:A,2,....J,Q,K一共 13 张。他先自己精心设计它们的顺序,然后正面朝下拿着,开始表演。

只见他先从最下面拿一张放到最上面,再从最下面拿一张翻开放桌子上,是 A;然后再从最下面拿一张放到最上面,再从最下面拿一张翻开放桌子上,是 2;......如此循环直到手中只有一张牌,翻开放桌子上,刚好是 K。

这时,桌上牌的顺序是:A,2,3,4,5,6,7,8,9,10,J,Q,K。

请你计算一下,小明最开始的时候手里牌的顺序是怎样的。

把结果写出来,逗号分割,小明“魔术”开始时,最下面的那张牌输出为第一个数据。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M
package Day_Day_work;

/**
 * @author yx
 * @date 2022-03-13 10:17
 */

public class 巧排扑克牌 {
// 1:输出是逗号+空格
        public static void main(String[] args) {
            System.out.print("7, A, Q, 2, 8, 3, J, 4, 9, 5, K, 6, 10");
    }
}

🎪题解分析:

💦1、第一题没啥好说的,自己花几分钟手撸一下,然后在花几分钟验证一下即可

💦2、实在不济,自己模拟一下题目,做个小手工,一张一张自己实现一下这个过程即可

 🎃2、质数拆分

🎯题目描述

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

将 2019 拆分为若干个两两不同的质数之和,一共有多少种不同的方法?

注意交换顺序视为同一种方法,例如 2 + 2017 = 2019 与 2017 + 2 = 2019视为同一种方法。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M
package Day_Day_work.problem;
/**
 * @author yx
 * @date 2022-03-13 10:52
 */
public class 质数拆分__01背包问题 {
    static long[] a=new long[2020];
    static int[] p=new int[2020];
    public static void main(String[] args) {
            a[0]=1;
            int n=1;
            for(int i=1;i<2019;i++)
            {
                if(pd(i))
                {
                    p[n++]=i;
                }
            }
        /**
         * 下面是01动规核心代码
         */
        for(int i=1;i<=n-1;i++) {
                for(int j=2019;j>=p[i];j--) {
                    a[j] += a[j-p[i]];
                }
            }
            System.out.println(a[2019]);
    }

    static boolean pd(int x) {//质数判断
        if(x==1)
        {
            return false;
        }
        for(int i=2;i<=(int) Math.sqrt(x);i++)
        {
            if(x%i==0)
            {
                return false;
            }
        }
        return true;
    }
}

🎪题解分析:

💦1、这个题目很容易理解错误,是若干两两不同的组成,而不是两个组成(博主踩过的坑)

💦2、将题目拆分成两个部分:质数判断、背包组合

难点分析:

💦1、能看出题目背后的本质,其实就是背包问题

💦2、熟练01背包问题

💦3、能快速写出质数判断的方法(暴力方法就可)

🖼️3、日志统计 

🎯题目描述

小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有 N 行。其中每一行的格式是:ts id

表示在 ts 时刻编号 id 的帖子收到一个"赞"。

现在小明想统计有哪些帖子曾经是"热帖"。如果一个帖子曾在任意一个长度为 D 的时间段内收到不少于 K个赞,小明就认为这个帖子曾是"热帖"。

具体来说,如果存在某个时刻 T 满足该帖在 [T,T+D)这段时间内(注意是左闭右开区间)收到不少于 K 个赞,该帖就曾是"热帖"。

给定日志,请你帮助小明统计出所有曾是"热帖"的帖子编号。

输入描述

输入格式:

第一行包含三个整数 N,D,K

以下 N 行每行一条日志,包含两个整数 ts 和 id。

其中,10^51≤K≤N≤105,0≤ts≤105,0≤id≤105。

输出描述

按从小到大的顺序输出热帖 id。

每个 id 一行。

输入输出样例

示例

输入

7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3

输出

1
3

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M
package Day_Day_work;

import java.util.*;

/**
 * @author yx
 * @date 2022-03-13 15:19
 */
public class 日志统计__尺取法 {
    static class R{
        int ts;//时刻
        int td;//id
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N=scanner.nextInt(),D=scanner.nextInt(),K=scanner.nextInt();
        R[] rs=new R[N];
        for (int i = 0; i < N; i++) {
            R r=new R();
            r.ts=scanner.nextInt();
            r.td=scanner.nextInt();
            rs[i]=r;
        }
        //匿名内部类定义排序器
        Arrays.sort(rs, new Comparator<R>() {
            @Override
            public int compare(R o1, R o2) {
                return o1.ts-o2.ts;//表示按时刻的升序来排列
            }
        });
        //用于给id计点赞数
        Map<Integer,Integer> cnt=new HashMap<>();
        //用于存储答案,TreeSet自动对集合中的元素进行升序排序
        SortedSet<Integer> answer=new TreeSet<Integer>();
        /*
          尺取法
         */
        int j=0;
        for (int i = 0; i < N; i++) {
            while (j<N&&rs[j].ts-rs[i].ts<D){//左闭右开,时间区间不能超过D
                int td=rs[j].td;
                Integer exist=cnt.get(td);
                if(exist!=null){//不为空的情况下
                    cnt.put(td,exist+1);//该id的点赞次数+1
                }else {//最开始的情况
                    cnt.put(td,1);//该id第一次出现,直接给赋值为1
                }
                if(cnt.get(td)>=K){//当点赞次数超过K时加入到answer集合中
                    answer.add(td);
                }
                j++;//往后继续取区间
            }
            //退出while循环后,i往后移动会+1,则当前的i的点赞数-1,因为后面的区间最小值为i+1
            //不包括i,将该id下的点赞数-1
            Integer c=cnt.get(rs[i].td);//获取该id下的点赞数
            if(c!=null){
                cnt.put(rs[i].td,c-1);//更新点赞数
            }
        }
        for (Integer i:answer) {
            System.out.println(i);
        }
    }
}

🎪题解分析:

💦1、该题采用尺取法,区间间隔移动,统计在D时间区间内每个id的获赞数

💦2、使用类绑定时刻和id

难点分析:

💦1、匿名内部类自定义排序器(定义了一个类来绑定时刻和id,所以要重写一下排序方法)

💦2、熟练使用HashMap和TreeSet

💦3、熟练使用尺取法

🎄4、递增三元组

🎯资源限制

时间限制:1.0s   内存限制:256.0MB

  给定三个整数数组
  A = [A1, A2, ... AN],
  B = [B1, B2, ... BN],
  C = [C1, C2, ... CN],
  请你统计有多少个三元组(i, j, k) 满足:
  1. 1 <= i, j, k <= N
  2. Ai < Bj < Ck

输入格式

  第一行包含一个整数N。
  第二行包含N个整数A1, A2, ... AN。
  第三行包含N个整数B1, B2, ... BN。
  第四行包含N个整数C1, C2, ... CN。

  对于30%的数据,1 <= N <= 100
  对于60%的数据,1 <= N <= 1000
  对于100%的数据,1 <= N <= 100000 0 <= Ai, Bi, Ci <= 100000

输出格式

  一个整数表示答案

样例输入

3
1 1 1
2 2 2
3 3 3

样例输出

27

package Day_Day_work;

import java.util.Arrays;
import java.util.Scanner;

/**
 * @author yx
 * @date 2022-03-13 16:02
 */
public class 递增三元组 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();
        int A[] = new int[N];
        int B[] = new int[N];
        int C[] = new int[N];
        for (int i = 0; i < N; i++) {
            A[i] = scanner.nextInt();
        }
        for (int i = 0; i < N; i++) {
            B[i] = scanner.nextInt();
        }
        for (int i = 0; i < N; i++) {
            C[i] = scanner.nextInt();
        }
        //计数
        int a = 0;
        int b = 0;
        int c = 0;
        //升序排列
        Arrays.sort(A);
        Arrays.sort(B);
        Arrays.sort(C);
        int j = 0;
        int k = 0;
        long ans=0;
        for (int i = 0; i < N; i++) {
            while (j<N&&A[j]<B[i])j++;
            while (k<N&&C[k]<=B[i])k++;
            ans+=(long) (N-k)*j;
        }
        System.out.println(ans);
    }
}

🎪题解分析:

💦1、先将A、B、C三个数组进行升序排序

💦2、以B数组为突破点,从左往右遍历A数组定位小于B[i]的A元素有j个

💦3、以B数组为突破点,从左往右遍历C数组定位小于等于B[i]的C元素有k个

💦4、那么该轮一共有(j)*(n-k)个三元组

💦5、按照该思路从左往右遍历B数组,累加每一轮的三元组数量

🎍5、外卖店优先级

🎯题目描述

"饱了么"外卖系统中维护着 NN 家外卖店,编号 1 ∼ NN。每家外卖店都有 一个优先级,初始时 (0 时刻) 优先级都为 0。

每经过 1 个时间单位,如果外卖店没有订单,则优先级会减少 1,最低减 到 0;而如果外卖店有订单,则优先级不减反加,每有一单优先级加 2。

如果某家外卖店某时刻优先级大于 5,则会被系统加入优先缓存中;如果 优先级小于等于 3,则会被清除出优先缓存。

给定 TT 时刻以内的 MM 条订单信息,请你计算 TT 时刻时有多少外卖店在优 先缓存中?

输入描述

第一行包含 3 个整数 N,M,TN,M,T。

以下 MM 行每行包含两个整数 ts,idts,id,表示 tsts 时刻编号 idid 的外卖店收到一个订单。

其中,1 \leq N,M,T \leq 10^5,1 \leq ts \leq T,1 \leq id \leq N1≤N,M,T≤105,1≤ts≤T,1≤id≤N。

输出描述

输出一个整数代表答案。

输入输出样例

示例

输入

2 6 6
1 1
5 2
3 1
6 2
2 1
6 2

输出

1

样例解释:

6 时刻时,1 号店优先级降到 3,被移除出优先缓存;2 号店优先级升到 6, 加入优先缓存。所以是有 1 家店 (2 号) 在优先缓存中。

运行限制

  • 最大运行时间:2s
  • 最大运行内存: 256M
package Day_Day_work;
import java.util.Scanner;

/**
 * @author yx
 * @date 2022-03-13 19:42
 */
/*
仔细读题:
1、优先级最低减到 0
2、优先级大于 5,则会被系统加入优先缓存(进入优先缓存后还有可能被移除)

思路:
1、先模拟,再全部遍历
 */
public class 外卖店优先__暴力模拟 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N=scanner.nextInt();//M行数据输入
        int M=scanner.nextInt();//N家店
        int T=scanner.nextInt();//给定的一个时刻
        int A[][]=new int[N][T];
        int ans=0;//计数
        for (int i = 0; i < M; i++) {
            int ts=scanner.nextInt();//输入时刻
            int id=scanner.nextInt();//输入店的id
            A[id-1][ts-1]+=1;//表示这家店来了一个订单
        }
        for (int i = 0; i < N; i++) {//对每一家店做处理
            int level=0;//优先级
            boolean k=false;//是否能够加入优先缓存
            for (int i1=0;i1<T;i1++){
                if(A[i][i1]==0){//表示没有订单
                    level-=1;
                    if(level<0){
                        level=0;
                    }
                    if (level<=3){
                        k=false;
                    }
                }else {
                    level+=(2*A[i][i1]);
                    if(level>5){
                        k=true;
                    }
                }
            }
            if(k){
                ans++;
            }
        }
        System.out.println(ans);
    }
}

🎪题解分析:

💦1、本题解为暴力方法,性价比最高

💦2、定义一个二维数组,行数表示店的数量,列数表示一共有多少个时刻

💦3、先将所有数据存入二维数组

💦4、遍历每一家店

难点分析:

💦1、优先级最低减到 0,就不会再减了

💦2、优先级大于 5,则会被系统加入优先缓存(但是进入优先缓存后还有可能被移除)

💦3、先模拟,再全部遍历

💖写在最后

每日一题,我们一直在路上,这次的题目有点小难度,比较有挑战性

也充分认识到了自己的不足,比如说在动规背包问题上的薄弱,博主接下来将有针对性地加强训练

“心若有所向往,何惧道阻且长,各位有志青年,一起加油 !”

欢迎一起交流讨论!

  • 59
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 69
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 69
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小羊不会飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值