蓝桥杯2013-Java B组省赛真题

前言

本文章只包含题目+答案,没有详细的分析过程(仅为了个人的归纳复盘使用)

题目以及讲解是看B站的视频:2013年-Java-B-题1_哔哩哔哩_bilibili

2013-Java省赛第一题——世纪末的星期

import java.util.Calendar;

//世纪末的星期
//熟悉日期api,在1970年之后都可以用
public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Calendar calendar = Calendar.getInstance();
        for(int year=1999;year<10000;year+=100)
        {
            calendar.set(Calendar.YEAR, year);
            calendar.set(Calendar.MONTH, 11);//默认是从0开始,所以11就是12个月
            calendar.set(Calendar.DAY_OF_MONTH, 31);//从1开始,设置12月
            if(calendar.get(Calendar.DAY_OF_WEEK)==1)//是星期日
            {
                System.out.println(year);
                break;
            }
        }
    }

}

答案:2299

关于这题的tips:

1.熟悉日期api:Java基础--常用API--日期相关API - 累成一条狗 - 博客园 (cnblogs.com)

2.set方法:两个参数(设置的项、设置的值)

3.注意日期的开始值(比如:Calendar.MONTH是从0开始的,所以设置11就是12月,日历从1开始的,星期日是1)

2013-Java省赛第二题——马虎的算式

//马虎的算式_枚举
public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int count = 0;
        for(int a=1;a<10;a++)
        {
            for(int b=1;b<10;b++)
            {
                if(a!=b)
                {
                    for(int c=1;c<10;c++)
                    {
                        if(c!=a&&c!=b)
                        {
                            for(int d=1;d<10;d++)
                            {
                                if(d!=a&&d!=b&&d!=c)
                                {
                                    for(int e=1;e<10;e++)
                                    {
                                        if(e!=a&&e!=b&&e!=c&&e!=d)
                                        {
                                            if((a*10+b)*(c*100+d*10+e)==(a*100+d*10+b)*(c*10+e))
                                            {
                                                count++;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        System.out.println(count);
    }

}

答案:142

关于这题的tips:

该题是枚举,认真写好每一个for循环和if条件就不会出错,注意检查。

2013-Java省赛第三题——振兴中华

//振兴中华_递归_深搜
//二叉树-只能往下或往右-动态规划
public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //做递归三要素:重复、变化、边界
        int count = f(0,0);
        System.out.println(count);
    }
    
    private static int f(int i,int j) {//i:行;j:列
        if(i==3 || j==4) return 1;//如果到了边界,就使其加1,不继续往下递归
        return f(i+1,j) + f(i,j+1);//将两种走法的路线数相加
        //向右、向下
    }

}

答案:35

关于这题的tips:

这题考的是递归-深度搜索、动态规划,蓝桥杯中此类的题目不少,需要分析出整个算法的逻辑,分为几步进行,然后写在方法中。

2013-Java省赛第四题——黄金连分数

import java.math.BigDecimal;
import java.math.BigInteger;

//黄金连分数(斐波拉契用迭代)
//1.化为求斐波拉契数列相邻两项的比值,到多少值?越多越精确,n/n+1项,n再往上增加,这个壁纸的小数点后101位是稳定的,也就是不变的
//2.double无法表示一百位的小数,BigInteger和BigDecimal(大数api)
public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BigInteger a = BigInteger.ONE;
        BigInteger b = BigInteger.ONE;
        for(int i=3;i<1000;i++)
        {
            BigInteger t = b;
            b = a.add(b);
            a = t;
        }
        BigDecimal divide = new BigDecimal(a,110).divide(new BigDecimal(b,110),BigDecimal.ROUND_HALF_DOWN);
        System.out.println(divide.toPlainString().substring(0,103));//101位,截取0.
        //提交的时候要进行101位的四舍五入
    }

}

答案:

0.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911375

斐波那契数列迭代(配合大数api)
        BigInteger a = BigInteger.ONE;
        BigInteger b = BigInteger.ONE;
        for(int i=3;i<1000;i++)
        {
            BigInteger t = b;
            b = a.add(b);
            a = t;
        }

关于这题的tips:

  1. 要先分析,发现每一层得出的结果,可以发现每一层的结果就是斐波拉契数列前一项与后一项的比值(斐波拉契数列:1,1,2,3,5,8......每一项等于前两项的和)

  1. 循环要到多少次?需要多次尝试才能得到一个稳定的值

  1. 因为double的精度无法算到小数点后一百位,所以使用BigInteger和BigDecimal(大数api)(divice是分数的函数)

  1. 最后需要将结果转化成字符串,用substring()方法截取小数点后101位数(注意!因为第100位需要进行四舍五入,所以要多截一位),而0.也占了两位数,所以是substring(0,103)

  1. 答案记得四舍五入

2013-Java省赛第五题——有理数类(程序阅读题)

需要填的是加法方法中的return值

package cn.edu.fjjxu;
//有理数类
public class Main05 {
    
    public static void main(String[] args) {
        Rational a = new Rational(1, 3);
        Rational b = new Rational(1, 6);
        Rational c = a.add(b);
        System.out.println(a+"+"+b+"="+c);
    }
    static class Rational{
        private long ra;
        private long rb;
        
        //求最大公约数
        private long gcb(long a,long b)
        {
            if(b==0) return a;
            return gcb(b, a%b);
        }
        
        //分子和分母约分
        public Rational(long a,long b)
        {
            ra = a;//分子
            rb = b;//分母
            long k = gcb(ra, rb);
            if(k>1)//需要约分
            {
                ra /= k;
                rb /= k;
            }
        }
        
        //加法:问题
        public Rational add(Rational x)
        {
            return new Rational(ra*x.rb+x.ra*rb,rb*x.rb);//问题
        }
        
        //乘法
        public Rational mul(Rational x)
        {
            return new Rational(ra*x.ra, rb*x.rb);
        }
        
        public String toString()
        {//ra作为分子,rb作为分母
            if(rb==1) return "" + ra;
            return ra + "/" + rb;
        }
    }
}

答案:new Rational(ra*x.rb+x.ra*rb,rb*x.rb)

关于这题的tips:

  1. 观察题目所给的信息可以发现每一个方法都对应了数学中的不同方法(最大公约数、约分等等)

  1. 既然要求的是加法,可以参考乘法的return值,找到分数加法运算的规律

2013-Java省赛第六题——三部排序(程序阅读题)

//三部排序_快排的变形
public class Main {
    public static void main(String[] args) {
        int[]arr = {25,18,-2,0,16,-5,33,21,0,19,-16,25,-3,0};
        sort(arr);
        for(int i=0;i<arr.length;i++){
            System.out.print(arr[i]+" ");
        }
    }
    static void sort(int[] x){
        int p = 0;//移动的指针
        int left = 0;//下标
        int right = x.length - 1;//最大下标
        
        while (p<=right) {
            if(x[p]<0){
                //元素小于0,将元素和left位置交换
                int t = x[left];
                x[left] = x[p];
                x[p] = t;
                left++;
                p++;
            }else if(x[p]>0){
                //元素大于0,将元素和right位置交换
                int t = x[right];
                x[right] = x[p];
                x[p] = t;
                right--;
            }else{
                //元素等于0
                p++;//代码填空位置
            }
        }
    }
}

答案:p++

关于本题的tips:

  1. (极限思维)快速求解,考虑一种极限的情况,数组全部都是0,那么就不发生交换,只要移动哨兵(也就是p指针)

  1. 本题是快速排序的变形,其实比快排更加简单,只需要归类,将正数、负数和零归成三类分别分析三个指针各自的动向即可

2013-Java省赛第七题——错误票据

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

//错误票据_枚举
public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner sc = new Scanner(System.in);
        ArrayList<Integer> list = new ArrayList<Integer>();
        int N = sc.nextInt();
        sc.nextLine();//吃掉整数后面的换行符
        for(int i=0;i<N;i++){
            
            String line = sc.nextLine();
            String[] split = line.split(" ");
            for(int j=0;j<split.length;j++){
                list.add(Integer.parseInt(split[j]));//解析成整数
            }
        }
//        System.out.println(list.size());ID的个数
        //对数组进行排序用array(Arrays.sort)对集合进行排序用collections
        Collections.sort(list);
        int a = 0;//a:断号
        int b = 0;//b:重号
        for(int i=1;i<list.size();i++){//边界从1开始!!
            if(list.get(i)-list.get(i-1)==2){
                a = list.get(i)-1;
            }
            //此处有坑!==:是比较对象,equals才是比较内容!!
            if(list.get(i).equals(list.get(i-1))){
                b = list.get(i);
            }
        }
        System.out.println(a+" "+b);
    }

}

关于本题的tips:

  1. 这题的第一个坑是关于输入方面的,输入N行,但是每行的列数不确定,需要多写一句sc.nextLine();(吃掉整数后面的换行符),并将ID号存进字符串集合中,用空格分隔开

  1. 排序方面:对数组进行排序用array(Arrays.sort)对集合进行排序用collections

  1. 这题的第二个坑:==:是比较对象,equals才是比较内容!所以条件应该写成list.get(i).equals(list.get(i-1))而不是list.get(i)==list.get(i-1),如果非要这样写,就改成list.get(i)-list.get(i-1)==0也是对的

2013-Java省赛第八题——幸运数

import java.util.Scanner;

//幸运数
public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner sc = new Scanner(System.in);
        int m = sc.nextInt();
        int n = sc.nextInt();
        int []a = new int[n];//存储数据的数组,范围给大一点才能找到保证重复的数值在后面
        for(int i=0;i<n;i++){
            a[i] = 2*i + 1;//奇数列
        }
        //已经把2的倍数(位置)给删除了
        
        int l = 1;//幸运数的下标,a[l]是幸运数
        while(true){
            int p = l+1;//数字向前挪动的坑位
            for(int i=l+1;i<n;i++){
                if((i+1)%a[l]==0){}
                else{
                    a[p] = a[i];//切换幸运数
                    p++;
                }
            }
    //      测试第一轮的输出
//            for(int i=0;i<n;i++){
//                System.out.print(a[i]+" ");
//            }
//            System.out.println();
            l++;
            if(a[l]>=n) break;
        }
        int count = 0;
        for(int i=0;i<n;i++){
            if(a[i]>=n) break;
            if(a[i]>m) count++;
        }
        System.out.println(count);
    }

}

关于本题的tips:

  1. 这题是需要去分析其中的逻辑关系的,首先是第一次删去数得到的序列其实就是奇数列,所以说初始序列可以直接生成奇数列

  1. 在解题的过程中可以先试一轮的值来验算得到的数列是否正确

  1. 这里可以将删去项变成是往前挪,这样的话不用一直重新定义下标

  1. 坑点:两个if语句的顺序不要写反了,不然题例中的21就要被count计进去了

  1. 这题需要认真分析!(主要是要搞懂指针的挪动规律)

2013-Java省赛第九题——带分数

import java.util.Scanner;

//带分数_枚举_全排列(递归)
public class Main { 
    static int result;
    static int N;
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner sc = new Scanner(System.in);
        N = sc.nextInt();
        int[] arr = {1,2,3,4,5,6,7,8,9};
        f(arr,0);
        System.out.println(result);
    }
    //确认某一个排列的第k位
    public static void f(int[] arr,int k){
        if(k==9){//全部确认
            check(arr);
            return;
        }else{
            //选定第k位
            for(int i=k;i<9;i++){
                //将第i位和第k位交换
                int t = arr[i];
                arr[i] = arr[k];
                arr[k] = t;
                
                //移交下一位去确认k+1位
                f(arr,k+1);
                
                //回溯(换回来)——深搜(退回来的时候,应该将之前的状态都清空,所以应该换回来)
                t = arr[i];
                arr[i] = arr[k];
                arr[k] = t;
            }
        }
    }
    
    //还要放加号和除法(枚举加号和除号的位置)
    public static void check(int[] arr) {
        //加号前的字符数最多是7
        for (int i = 1; i <= 7; i++) {
            int num1 = toInt(arr,0,i);//加号前面的一段整数
            if(num1>=N){//如果其实+前面的数额已经超过了N,那么就没必要计算了
                continue;
            }
            //除号前面的字符数
            for (int j = 1; j <= (8-i); j++) {
                int num2 = toInt(arr, i, j);
                int num3 = toInt(arr, i+j, 9-i-j);
                if((num2%num3==0)&&(num1+num2/num3==N)){
                    result++;
                }
            }
        }
    }
    //将数组变成整数
    private static int toInt(int[] arr, int pos, int len) {
        int t = 1;
        int count = 0;
        for (int i = pos+len-1; i >= pos; i--) {
            count += arr[i]*t;
            t*=10;
        }
        return count;
    }

}

用递归来写全排列是必然要掌握的!

全排列的写法
    static int[] arr = {1,2,3,4,5,6,7,8,9};
    static int count;
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        f(arr,0);
    }
    //确认某一个排列的第k位
    private static void f(int[] arr,int k){
        if(k==9){//全部确认
            if(check(arr)){
                count++;
            }
            print(arr);
        }
        //选定第k位
        for(int i=k;i<arr.length;i++){
            //将第i位和第k位交换
            int t = arr[i];
            arr[i] = arr[k];
            arr[k] = t;
            
            //移交下一位去确认k+1位
            f(arr,k+1);
            
            //回溯(换回来)——深搜(退回来的时候,应该将之前的状态都清空,所以应该换回来)
            t = arr[i];
            arr[i] = arr[k];
            arr[k] = t;
        }
        
    }
    private static void print(int[] arr2) {
        for(int i=0;i<arr.length;i++){
            System.out.print(arr[i]);
        }
        System.out.println();
    }
将数组变成整数的模板
   //将数组变成整数
    private static int toInt(int[] arr, int pos, int len) {
        int t = 1;
        int count = 0;
        for (int i = pos+len-1; i >= pos; i--) {
            count += arr[i]*t;
            t*=10;
        }
        return count;
    }

关于这题的tips:

  1. 首先需要掌握的肯定是全排列的写法,先写出9个数字的全排列

  1. 然后就是考虑两个运算符号的位置

  1. 最后将数组转化成整数,条件符合的情况利用计数变量count++

  1. 这个题很难去验算了,就是保证题例都能通过,而且逻辑和性能方面的问题

2013-Java省赛第十题——连号区间数

import java.util.Scanner;
//连号区间数
public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] arr = new int[n+1];
        for (int i = 1; i <= n; i++) {
            arr[i] = sc.nextInt();
        }
        int count = 0;
        for (int i = 1; i <= n; i++) {
            int max = arr[i];
            int min = arr[i];
            for (int j = i; j <= n; j++) {//]右边界的位置
                if(arr[j]>max) max = arr[j];
                if(arr[j]<min) min = arr[j];
                if(i==j) {
//                    System.out.printf("[%d,%d]\n",i,j);
                    count++;
                }else{//i<j怎么判断[i,j]是连号区间呢?
                    if(max-min==j-i) {
//                        System.out.printf("[%d,%d]\n",i,j);
                        count++;
                    }
                }
            }
        }
        System.out.println(count);
    }

}

关于本题的tips:

分析连号的规律,设置最大值和最小值就能写出来

总结

程序填空题(填结果)

01世纪末的星期:枚举每个世纪末,判断是否星期天 (Calendar api)

02马虎的算式:枚举每个位上的数字,组合判断

03振兴中华:找重复中的变化,找边界

04黄金连分数:1. 识别问题等价于斐波那契的n项和n+1项的比值;2. n要多少才够;3.怎么处理很大的数和精度要求很高的浮点数

程序填空题(填代码)

05有理数类:面向对象+分数加法(通分与约分)

06三部排序:快速排序(三指针区间法)变形;极限思维(考虑全部是0)

编程题

07错误票据:输入比较特殊,排序,迭代(获取断号和重号),输出

08幸运数:模拟筛选过程,枚举计数

09带分数:1-9用递归做全排列,对每一个排列,都枚举+和/的位置,然后进行检查

10连号区间数:枚举所有区间,检查这个区间里面的数排序后是否连号


2013年的题目大部分都是考枚举递归方面的算法

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值