14届蓝桥杯省赛Java A 组Q1~Q3

题目链接:

Q1

蓝桥云课:特殊日期

Q2

蓝桥云课:与或异或

洛谷:P13877 [蓝桥杯 2023 省 Java A] 与或异或

Q3

蓝桥云课:平均

洛谷:P13878 [蓝桥杯 2023 省 Java/Python A] 平均

算法原理:

Q1解法:暴力枚举

时间复杂度O(1)

枚举每个年份、每个月份、每个天数,算出各个数位上的总和进行比较

其中2月份比较特殊,按照闰年的计算规则:四年一闰,百年不闰,四百年再闰

得出判断闰年的代码:(i%4==0&&i%100!=0)||(i%400==0)

Q2解法:递归、搜索与回溯

时间复杂度O(3¹⁰)

将题目的示例转化成数组

会变成

java 复制代码
1 0 1 0 1 //第0行
1 1 1 0   //第1行
1 1 1     //第2行
1 0       //第3行
1         //第4行

我们发现第1行第1个元素是由第0行第1个元素和第0行第2个元素决定的

第1行第2个元素是由第0行第2个元素和第0行第3个元素决定的

......

第2行第1个元素是由第1行第1个元素和第1行第2个元素决定的

......

因此大规模的问题可以分成相似的子问题来解决,所以我们采用递归的解法

由于针对每两个数有3种选择方式:&、|、^,因此我们要采用回溯的方法来逐个尝试当前位置分别采用&、|、^得出的结果

其实这里类似用到了隐式回溯,因为在数组中可以直接覆盖掉数据,达到"回溯"的效果

类似题目如下👇

A.每日一题:1415. 长度为 n 的开心字符串中字典序第 k 小的字符串

A.每日一题------1980. 找出不同的二进制字符串

E.位运算-基础------3211. 生成不含相邻零的二进制字符串

A.每日一题:3129. 找出所有稳定的二进制数组 I +3130. 找出所有稳定的二进制数组 II

显式回溯与隐式回溯的区别

底层都是回溯思想,只是写法随容器变而已

①固定长度结构(char []、数组)→ 天然适合隐式回溯,写法更干净

②变长结构(StringBuffer、List、Builder)→ 必须显式回溯,不然必错

具体步骤:

Ⅰ按题目要求初始化第0行

Ⅱdfs方法设计:

①如果到了第5行,说明第4行第一个数即为结果,如果是1,方案数+1

②填写当前位置ret[i][j]的值:取决于ret[i-1][j]和ret[i-1][j+1]

分别填写ret[i-1][j]&ret[i-1][j+1]、ret[i-1][j] | ret[i-1][j+1]、ret[i-1][j]^ret[i-1][j+1]的结果

③填写完后判断当前位置是否是当前行的最后一个位置

如果是最后一个位置:开启下一行,从第1个位置开始填,否则就继续填当前行的下一个位置

Q3解法:贪心

时间复杂度O(n logn)

思路很简单,我们要保证0~9每个数都出现n/10次,那么为了保证总的代价和最小,肯定要移除代价小的

因此我们做出决定:

①用大小为10的数组表示数字0~9,将它们出现的代价挂在后面

②为了保留代价大的,移除代价小的,通过降序排序实现

图解如下👇

其中对顺序表降序排序直接用:Collections.sort(nums[i],Collections.reverseOrder());

关键易错点复盘

①创建大小为10的数组,其中每个元素是一个顺序表(此题的形式):

java 复制代码
List<Integer>[] nums=new ArrayList[10];

及时初始化,创建空顺序表:

java 复制代码
for(int i=0;i<10;i++) nums[i]=new ArrayList<>();

②创建一个顺序表,其中每个元素是大小为10的数组:

java 复制代码
List<int[]> list=new ArrayList<>();

及时初始化,添加数组

java 复制代码
list.add(new int[10]);//第一个元素
list.add(new int[10]);//第二个元素
list.add(new int[10]);//第三个元素
//赋值过程
list.get(0)[5]=999;
list.get(1)[9]=666;

Java代码:

Q1

java 复制代码
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        int ret=0;
        for(int i=1900;i<9999;i++){//枚举年份
            //计算年份各位的和
            String s=i+"";
            int sum=0;
            for(char c:s.toCharArray()) sum+=c-'0';
            for(int j=1;j<=12;j++){//枚举月份
                int n=0;//确定天数
                if(j==1||j==3||j==5||j==7||j==8||j==10||j==12) n=31;
                else if(j==2){
                    //闰年
                    boolean isleap=(i%4==0&&i%100!=0)||(i%400==0);
                    if(isleap) n=29;
                    //平年
                    else n=28;
                }else n=30;
                for(int k=1;k<=n;k++){
                    if(sum==getsum(j)+getsum(k)) ret++;
                }
            }
        }
        System.out.println(ret);
    }
    //获取各数位上的和
    private static int getsum(int n){
        int ret=0;
        while(n>0){
            ret+=n%10;
            n/=10;
        }
        return ret;
    }
}

Q2

java 复制代码
import java.util.*;
public class Main{
    private static int cnt=0;
    public static void main(String[] args){
        int[][] ret=new int[5][5];
        ret[0][0]=1;
        ret[0][1]=0;
        ret[0][2]=1;
        ret[0][3]=0;
        ret[0][4]=1;
        //从第1行第0个数开始计算
        dfs(ret,1,0);
        System.out.println(cnt);
    }
    private static void dfs(int[][] ret,int i,int j){
        if(i==5){
            cnt+=ret[4][0]==1?1:0;
            return;
        }
        //k=0:&  k=1:|  k=2:^
        for(int k=0;k<3;k++){
            if(k==0) ret[i][j]=ret[i-1][j]&ret[i-1][j+1];
            else if(k==1) ret[i][j]=ret[i-1][j]|ret[i-1][j+1];
            else ret[i][j]=ret[i-1][j]^ret[i-1][j+1];
            //判断j是不是当前行最后一个节点
            if(j==4-i) dfs(ret,i+1,0);
            else dfs(ret,i,j+1);
        }
    }
}

Q3

java 复制代码
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int t=n/10;
        long ret=0;
        List<Integer>[] nums=new ArrayList[10];
        //初始化每个位置为一个空顺序表
        for(int i=0;i<10;i++) nums[i]=new ArrayList<>();
        for(int i=0;i<n;i++){
            int a=sc.nextInt();
            int b=sc.nextInt();
            nums[a].add(b);
        }
        //对数组中的每个顺序表降序排序
        for(int i=0;i<10;i++){
            if(nums[i].size()<=t) continue;
            Collections.sort(nums[i],Collections.reverseOrder());
            for(int j=t;j<nums[i].size();j++) ret+=nums[i].get(j);
        }
        System.out.println(ret);
        sc.close();
    }
}
相关推荐
你不是我我5 小时前
【Java 开发日记】HTTP3 性能更好,为什么内网微服务依然多用 HTTP2?HTTP2 内网优势是什么?
java·开发语言·微服务
雪碧聊技术5 小时前
大模型爆火!Java后端如何抓住Agent全栈开发的风口
java·大模型·agent·全栈开发
IT大白鼠5 小时前
AIGC性能的关键瓶颈:算力、数据、算法三者如何互相制约?
算法·aigc
tjl521314_215 小时前
04C++ 名称空间(Namespace)
开发语言·c++
赏金术士5 小时前
Kotlin 数据流与单双向绑定
android·开发语言·kotlin
白雪茫茫6 小时前
监督学习、半监督学习、无监督学习算法详解
python·学习·算法·ai
FengyunSky6 小时前
浅析 空间频率响应 SFR 计算
算法
树下水月6 小时前
PHP 一种改良版的雪花算法
算法·php·dreamweaver
逻辑驱动的ken6 小时前
Java高频面试场景题25
java·开发语言·深度学习·面试·职场和发展
一只数据集7 小时前
全尺寸人形机器人灵巧手力觉触觉数据集-2908条ROSbag数据覆盖14大应用场景深度解析
大数据·人工智能·算法·机器人