赛题目录

  • A.美丽的2(签到)
  • 1.原试题
  • 2.简要分析
  • 3.实现代码
  • 4.答案
  • B.扩散(多源BFS)
  • 1.原试题
  • 2.简要分析
  • 3.实现代码
  • 4.答案
  • C.阶乘约数(数论)
  • 1.原试题
  • 2.简要分析
  • 3.实现代码
  • 4.答案
  • D.本质上升序列(dp)
  • 1.原试题
  • 2.简要分析
  • 3.实现代码
  • 4.答案
  • D.玩具蛇(DFS)
  • 1.原试题
  • 2.简要分析
  • 3.实现代码
  • 4.答案
  • 总结



A.美丽的2(签到)

1.原试题

蓝桥杯javac组难吗 蓝桥杯javab组真题解析_算法

2.简要分析

  • 签到题,遍历所有数,将数字转成字符串,判断是否包含2即可。

3.实现代码

public class _2020_A {
    public static void main(String[] args) {
        int ans = 0;
        for(int i = 1; i <= 2020; i++){
            String s = String.valueOf(i);
            if(s.contains("2")){
                //System.out.println(s);
                ans++;
            }
        }
        System.out.println(ans);
    }
}

4.答案

563



B.扩散(多源BFS)

1.原试题

蓝桥杯javac组难吗 蓝桥杯javab组真题解析_java_02

2.简要分析

  • 多源BFS,需要注意画布是无限大的,负坐标也可能扩散到,需要将初始四个坐标整体往右下角移动。
  • 每一层的扩散算一步,总共2020层BFS,就是扩散了2020分钟。
  • 数量级是1亿,几秒可以跑完。

3.实现代码

public class _2020_B {
    static class Node{
        int x;
        int y;

        public Node(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    static int[][] grid = new int[10000][10000];
    static int[][] dist = new int[10000][10000];
    static int[] dx = {-1,0,1,0};
    static int[] dy = {0,1,0,-1};

    public static void main(String[] args) {
        grid[4000][4000] = 1;
        grid[6020][4011] = 1;
        grid[4011][4014] = 1;
        grid[6000][6000] = 1;

        bfs();

        int ans = 0;
        for(int i = 0; i < 10000; i ++){
            for(int j = 0; j < 10000; j++){
                if(grid[i][j] == 1){
                    ans++;
                }
            }
        }

        System.out.println(ans);
    }

    static void bfs(){
        Queue<Node> q = new LinkedList<>();

        q.offer(new Node(4000,4000));
        q.offer(new Node(6020,4011));
        q.offer(new Node(4011,4014));
        q.offer(new Node(6000,6000));

        while(!q.isEmpty()){
            Node node = q.peek(); q.poll();

            if(dist[node.x][node.y] == 2020){
                return;
            }

            for(int i = 0; i < 4; i++){
                int x = node.x + dx[i];
                int y = node.y + dy[i];
                if(grid[x][y] == 1){
                    continue;
                }
                grid[x][y] = 1;
                q.offer(new Node(x,y));
                dist[x][y] = dist[node.x][node.y] + 1;
            }
        }
    }
}

4.答案

20312088


C.阶乘约数(数论)

1.原试题

蓝桥杯javac组难吗 蓝桥杯javab组真题解析_蓝桥杯javac组难吗_03

2.简要分析

  • 是一道数论的题目,需要掌握以下的基础数论知识:(阶乘数定理)
  • 任意一个正整数 X 都可以表示成若干个质数乘积的形式:
    蓝桥杯javac组难吗 蓝桥杯javab组真题解析_搜索_04
  • X的约数个数n为:
    蓝桥杯javac组难吗 蓝桥杯javab组真题解析_算法_05
  • 接下来只需要求出1-100中所有的质数,然后将100!用这些质数表示出来,得到每个质数的指数,最后相乘就能得到约数的个数。
  • 需要使用long型存储答案。

3.实现代码

public class _2020_C {

    static long ans = 1;
    static int[] t = new int[101];

    //判断一个数是不是素数
    static boolean issu(int n){
        for(int i = 2; i <= Math.sqrt((double)n); i++){
            if(n % i == 0){
                return false;
            }
        }
        return true;
    }
    //将1-100中所有的素数加入t表中 初始化为1,最后计算约数个数时不需要再加1
    static void addt(){
        t[2] = 1;
        for(int i = 3; i <= 100 ; i++){
            if(issu(i)){
                t[i] = 1;
            }
        }
    }

    public static void main(String[] args) {
        addt();

        for(int i = 2; i <= 100; i++){
            int x = i;
            //遍历每个质数 用质数将x表示出来
            for(int j = 2; j<= 100; j++){
                if(t[j]!=0){
                    while(x % j == 0){
                        x /= j;
                        //质数j的指数加1
                        t[j] ++;
                    }
                }
            }
        }
        //统计所有质数的指数,得到答案
        for(int i = 2; i <= 100; i++){
            if(t[i]!=0){
                ans*=(t[i]);
            }
        }
        System.out.println(ans);
    }
}

4.答案

39001250856960000


D.本质上升序列(dp)

1.原试题

蓝桥杯javac组难吗 蓝桥杯javab组真题解析_蓝桥杯_06


数据如下:(200个小写字母)

tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhfiadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqijgihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmadvrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkqhfwl

2.简要分析

  • 递增子序列的计数问题,注意一个字符也算,取字符的位置不同但最后子序列相同也只算一种。
  • dp[i]表示到以第i个字符结尾的递增子序列的个数。(i >= 0
  • 0 < j < i,如果c[i] > c[j]c[j]算入新的递增子序列中,那么dp[i] += dp[j]
  • 如果c[i] == c[j]c[i]c[j]的递增子序列数量存在重复部分,那么dp[i] -= dp[j]
  • 如果c[i] < c[jc[j]dp[i]没有贡献。

3.实现代码

public class _2020_D {

    static String s = "tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhfiadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqijgihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmadvrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkqhfwl";
    static int ans;

    public static void main(String[] args) {
        char cs[] = s.toCharArray();
        int dp[] = new int[200];
        for(int i = 0; i < 200; i++){
            dp[i] = 1;
        }
        for(int i = 0; i < cs.length; i++){
            for(int j = 0; j < i; j++){
                if(cs[i] >cs[j]){
                    dp[i] += dp[j];
                }
                if(cs[i] == cs[j]){
                    dp[i] -= dp[j];
                }
            }
        }

        for(int i = 0; i < dp.length; i++){
            ans+=dp[i];
        }

        System.out.println(ans);
    }
}

4.答案

3616159


D.玩具蛇(DFS)

1.原试题

蓝桥杯javac组难吗 蓝桥杯javab组真题解析_蓝桥杯_07

2.简要分析

  • 经典DFS问题,尝试以每一个格子为1,走出一条路径,最后统计路径总数。注意每次尝试以新的格子为1时,要把方格全部清空。

3.实现代码

public class _2020_E {

    static int[] dx = {-1,0,1,0};
    static int[] dy = {0,1,0,-1};
    static int[][] grid = new int[4][4];
    static int ans;

    static void init(){
        for(int i = 0; i < 4; i++){
            for(int j = 0; j < 4; j++){
                grid[i][j] = 0;
            }
        }
    }

    public static void main(String[] args) {
        for(int i = 0; i < 4; i++){
            for(int j =0; j < 4; j++){
                init();
                grid[i][j] = 1;
                dfs(i,j,1);
            }
        }
        System.out.println(ans);
    }


    static void dfs(int x,int y,int step){
        for(int i = 0; i < 4; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];

            if(nx > 3 || ny > 3 || nx < 0 || ny < 0 || grid[nx][ny] == 1){
                continue;
            }
            if(step == 15){
                ans++;
            }
            grid[nx][ny] = 1;
            dfs(nx,ny,step+1);
            grid[nx][ny] = 0;
        }
    }
}

4.答案

552


总结

  • 国赛填空题除了第一题签到外,其余的都需要对经典算法熟悉,并且能快速编码。
  • 数论的基本知识,DFS,BFS,基础dp,都需要非常熟悉。

ATFWUS