第十届蓝桥杯Java省赛A组答案整理

平方和

题目描述

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

小明对数位中含有 2、0、1、92、0、1、9 的数字很感兴趣,在 11 到 4040 中这样的数包括 1、2、9、101、2、9、10 至 32、3932、39 和 4040,共 2828 个,他们的和是 574574,平方和是 1436214362。

注意,平方和是指将每个数分别平方后求和。

请问,在 11 到 20192019 中,所有这样的数的平方和是多少?

package lanqiao;

public class lq1 {
    public static void main(String[] args) {
        long ans = 0;
        for(int i = 0;i <= 2019; i++){
            String num = i +"";
            if(num.contains("0")||num.contains("1")||num.contains("2")||num.contains("9")){
                ans += i*i;
            }
        }
        System.out.println(ans);
    }
}

数列求值

题目描述

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

给定数列 1,1,1,3,5,9,17,⋯1,1,1,3,5,9,17,⋯,从第 44 项开始,每项都是前 33 项的和。

求第 2019032420190324 项的最后 44 位数字。

package lanqiao;

public class lq2 {
    public static void main(String[] args) {
        int a = 1,b = 1, c= 1,d = 0;
        for(int i = 4; i<=20190324;i++){
            d= (a+b+c)%10000;
            a=b;
            b=c;
            c=d;
        }
        System.out.println(d);
    }
}

最大降雨量

题目描述

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

由于沙之国长年干旱,法师小明准备施展自己的一个神秘法术来求雨。

这个法术需要用到他手中的 4949 张法术符,上面分别写着 11 至 4949 这 4949 个数字。法术一共持续 77 周,每天小明都要使用一张法术符,法术符不能重复使用。

每周,小明施展法术产生的能量为这周 77 张法术符上数字的中位数。法术 施展完 77 周后,求雨将获得成功,降雨量为 77 周能量的中位数。

由于干旱太久,小明希望这次求雨的降雨量尽可能大,请大最大值是多少?

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        System.out.println("34");
        scan.close();
    }
}
//直接最大的中位数,49-3*4-3

题目描述

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

下图给出了一个迷宫的平面图,其中标记为 11 的为障碍,标记为 00 的为可以通行的地方。

010000
000100
001001
110000

迷宫的入口为左上角,出口为右下角,在迷宫中,只能从一个位置走到这 个它的上、下、左、右四个方向之一。

对于上面的迷宫,从入口开始,可以按 DRRURRDDDR 的顺序通过迷宫, 一共 1010 步。其中 D、U、L、RD、U、L、R 分别表示向下、向上、向左、向右走。 对于下面这个更复杂的迷宫(3030 行 5050 列),请找出一种通过迷宫的方式,其使用的步数最少,在步数最少的前提下,请找出字典序最小的一个作为答案。

请注意在字典序中 D<L<R<U。

package lanqiao;

import java.util.LinkedList;
import java.util.Scanner;

public class lq3 {
    static class Node{
        int x;
        int y;
        String str;
        public Node(int x, int y, String str){
            this.x = x;
            this.y = y;
            this.str = str;
        }
    }
    static char [][]graph = new char[30][50];
    static int[] dx = {1, 0, 0, -1};
    static int[] dy = {0, -1, 1, 0};
    static char[] path = {'D','L','R','U'};
    static int[][] visited = new int[30][50];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        for(int i = 0; i < 30; i++){
            graph[i] = sc.nextLine().toCharArray();
        }
        sc.close();
        visited[0][0] = 1;
        LinkedList<Node> queue = new LinkedList<>();
        queue.add(new Node(0,0,""));
        String answer = "";
        while(!queue.isEmpty()){
            Node cur = queue.poll();
            int x = cur.x;
            int y = cur.y;
            String str = cur.str;
            if(x == 29 && y == 49){
                answer = str;
                break;
            }
            for(int i = 0; i < 4; i++){
                int newX = x + dx[i];
                int newY = y + dy[i];
                if(newX >= 0 && newX < 30 && newY >= 0 && newY < 50 && visited[newX][newY]!=1 && graph[newX][newY] == '0'){
                    visited[newX][newY] = 1;
                    queue.add(new Node(newX, newY, str+path[i]));
                }
            }
        }
        System.out.println(answer);
    }
}

RSA解密

题目描述

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

RSA 是一种经典的加密算法。它的基本加密过程如下。

首先生成两个质数 p,qp,q,令 n=p⋅qn=p⋅q,设 dd 与 (p−1)⋅(q−1)(p−1)⋅(q−1) 互质,则可找到 ee 使得 d⋅ed⋅e 除 (p−1)⋅(q−1)(p−1)⋅(q−1) 的余数为 11。

n,d,en,d,e 组成了私钥,n,dn,d 组成了公钥。

当使用公钥加密一个整数 XX 时(小于 nn),计算 C=Xd mod nC=Xd mod n,则 CC 是加密后的密文。

当收到密文 CC 时,可使用私钥解开,计算公式为 X=Ce mod nX=Ce mod n。

例如,当 p=5,q=11,d=3p=5,q=11,d=3 时,n=55,e=27n=55,e=27。

若加密数字 2424,得 243 mod 55=19243 mod 55=19。 解密数字 1919,得 1927 mod 55=241927 mod 55=24。

现在你知道公钥中 n=1001733993063167141,d=212353n=1001733993063167141,d=212353,同时你截获了别人发送的密文 C=20190324C=20190324,请问,原文是多少?

import java.math.BigInteger;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    public static void main(String[] args) {
        long d = 212353; // 已知
        long c = 20190324; // 已知
        long n = 1001733993063167141L; // 已知
        long q = 0, p = 0, e = 0; // 未知
//        for (int i = 2; i <= Math.sqrt(n); i++) {
//            if (n % i == 0) {
//                q = i; // 已知n=q*p , 可得q
//                break;
//            }
//        }
//        p = n / q; // 已知n和q,可得p
        q = 891234941;
        p = 1123984201;
        // 通过python的pow(d,-1,(q-1)*(p-1)),乘法逆元的求出e=823816093931522017
        // pow(底数,指数,模数),相当于modPow,当指数为-1时就是乘法逆元(前提是底数和指数互质)
        System.out.println(new BigInteger("20190324").modPow(new BigInteger("823816093931522017"),
                new BigInteger("1001733993063167141")));
    }
}

完全二叉树的权值

题目描述

给定一棵包含 NN 个节点的完全二叉树,树上每个节点都有一个权值,按从 上到下、从左到右的顺序依次是 A1,A2,⋅⋅⋅ANA1​,A2​,⋅⋅⋅AN​,如下图所示:

现在小明要把相同深度的节点的权值加在一起,他想知道哪个深度的节点 权值之和最大?如果有多个深度的权值和同为最大,请你输出其中最小的深度。

注:根的深度是 1。

输入描述

第一行包含一个整数 N(1≤N≤105)N(1≤N≤105)。

第二行包含 NN 个整数 A1,A2,⋅⋅⋅AN(−105≤Ai≤105)A1​,A2​,⋅⋅⋅AN​(−105≤Ai​≤105)。

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改


public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        int []arr = new int[n];
        for(int i = 0; i < n; i++){
          arr[i] = scan.nextInt();
        }
        int max = arr[0];
        int count = 1;
        int res = 0;
//按行遍历树
        for(int i = 1; i < n; i++){
          int sum = 0;
          for(int j = i; j < i + Math.pow(2,count)&&j<n;j++){
            sum+=arr[j];
          }
          if(sum>max){
            max = sum;
            res = count;
          }
          count++;
          i*=2;
        }
        System.out.println(res+1);
        //在此输入您的代码...
        scan.close();
    }
}

外卖店优先级

题目描述

"饱了么"外卖系统中维护着 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≤N,M,T≤105,1≤ts≤T,1≤id≤N1≤N,M,T≤105,1≤ts≤T,1≤id≤N。

import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int N = scan.nextInt();//N家店
        int M = scan.nextInt();//订单
        int T = scan.nextInt();//给定T时刻
        int count = 0;//记录有几家加入优先缓存
        int t = 1;//当前时刻

        int[][] arr_M = new int[M][2];//订单列表 第一个代表时刻 第二个代表店
        int[][] arr_N = new int[N][2];//商店的优先级列表 第一个代表店的优先级 第二个0代表该时刻没有更新 1则相反,每个时刻重新归0
        int[] arr_T = new int[N];//记录每家店是否加入优先缓存 1代表加入 0相反
        for (int i = 0; i < arr_M.length; i++) {
            for (int j = 0; j < arr_M[i].length; j++) {
                arr_M[i][j] = scan.nextInt();
            }
        }
        scan.close();
        while(t <= T){
            for (int i = 0; i < arr_N.length; i++) {
                arr_N[i][1] = 0;
            }
            for (int i = 0; i < arr_M.length; i++) {//判断该时刻有没有这个店的订单 每有一单优先级加2
                if (arr_M[i][0] == t) {
                    arr_N[arr_M[i][1] - 1][0] += 2;
                    arr_N[arr_M[i][1] - 1][1] = 1;// 同时记录该时刻该店有更新
                }
            }
            for (int i = 0; i < arr_N.length; i++) {
                if (arr_N[i][1] == 0 && arr_N[i][0] != 0) {//如果本次没有订单 优先级就减1
                    arr_N[i][0] -= 1;
                }
                if (arr_N[i][0] > 5) {
                    arr_T[i] = 1;
                } else if (arr_N[i][0] <= 3) {
                    arr_T[i] = 0;
                }
            }
            t++;
        }
        for (int i = 0; i < arr_T.length; i++) {
            if (arr_T[i] == 1){
                count++;
            }
        }
        System.out.println(count);


    }
}

修改数组

题目描述

给定一个长度为 NN 的数组 A=[A1,A2,⋅⋅⋅,AN]A=[A1​,A2​,⋅⋅⋅,AN​],数组中有可能有重复出现的整数。

现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改A2,A3,⋅⋅⋅,ANA2​,A3​,⋅⋅⋅,AN​。

当修改 AiAi​ 时,小明会检查 AiAi​ 是否在 A1A1​ ∼ Ai−1Ai​−1 中出现过。如果出现过,则小明会给 AiAi​ 加上 1 ;如果新的 AiAi​ 仍在之前出现过,小明会持续给 AiAi​ 加 1 ,直 到 AiAi​ 没有在 A1A1​ ∼ Ai−1Ai​−1 中出现过。

当 ANAN​ 也经过上述修改之后,显然 AA 数组中就没有重复的整数了。

现在给定初始的 AA 数组,请你计算出最终的 AA 数组。

输入描述

第一行包含一个整数 NN。

第二行包含 NN 个整数 A1,A2,⋅⋅⋅,ANA1​,A2​,⋅⋅⋅,AN​。

其中,1≤N≤105,1≤Ai≤1061≤N≤105,1≤Ai​≤106。

输出描述

输出 NN 个整数,依次是最终的 A1,A2,⋅⋅⋅,ANA1​,A2​,⋅⋅⋅,AN​。

输入输出样例

示例

输入

5
2 1 1 3 4

输出

2 1 3 4 5
import java.util.*;

public class Main {
    private static Map<Integer, Integer> parent = new HashMap<>();

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int N = scan.nextInt();
        
        for (int i = 0; i < N; i++) {
            int x = scan.nextInt();
            int found = find(x);  // 找到当前可用的最小位置
            System.out.print(found + " ");
        }
        scan.close();
    }

    // 并查集查找(带路径压缩)
    private static int find(int x) {
        if (!parent.containsKey(x)) {  // x未被占用,直接返回
            parent.put(x, x + 1);      // 占用x,并指向下一个位置
            return x;
        }
        int next = find(parent.get(x));  // 递归查找下一个可用位置
        parent.put(x, next);             // 路径压缩
        return next;
    }
}

 

糖果

题目描述

糖果店的老板一共有 MM 种口味的糖果出售。为了方便描述,我们将 MM 种口味编号 1∼ MM。

小明希望能品尝到所有口味的糖果。遗憾的是老板并不单独出售糖果,而是 KK 颗一包整包出售。

幸好糖果包装上注明了其中 KK 颗糖果的口味,所以小明可以在买之前就知道每包内的糖果口味。

给定 NN 包糖果,请你计算小明最少买几包,就可以品尝到所有口味的糖果。

输入描述

第一行包含三个整数 N,M,KN,M,K。

接下来 NN 行每行 KK 个整数 T1,T2,⋅⋅⋅,TKT1​,T2​,⋅⋅⋅,TK​,代表一包糖果的口味。

其中,1≤N≤100,1≤M≤20,1≤K≤20,1≤Ti≤M1≤N≤100,1≤M≤20,1≤K≤20,1≤Ti​≤M。

输出描述

输出一个整数表示答案。如果小明无法品尝所有口味,输出 −1。

输入输出样例

示例

输入

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

输出

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

public class Main {

    static Scanner scanner = new Scanner(System.in);
    static int dp[];
    static int state[];

    public static void main(String[] args) {
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        int k = scanner.nextInt();
        dp = new int[(1 << 20) + 5];//用于表示某状态的最少购买次数
        state = new int[n+10];
        Arrays.fill(dp, -1);//不用bool[] 是因为我们要保存最少次数,那怎么表示有没有访问过呢? 用-1表示
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < k; j++) {
                int a = scanner.nextInt();
                state[i] |= 1 << (a-1);//添加状态
            }
            dp[state[i]] = 1;//标记为1,因为只能从这些开始购买,为后面的状态做基础
        }

        //从某背包开始,依次遍历,从中不断标记最小值
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < (1 << m); j++) {
                if (dp[j] == -1) continue;//如果本身不属于 售卖列表的情况就continue,因为只能从售卖列表中选择
                if (dp[j|state[i]] == -1) {
                    //另一种设想就是: 当原本情况下,买售卖列表中的,发现 状态并没有被试过
                    dp[j|state[i]] = dp[j] + dp[state[i]];
                }
                else {
                    //如果↑ 已经存在了,那么比较大小
                    dp[j|state[i]] = Math.min(dp[j]+dp[state[i]], dp[j|state[i]]);
                }

            }
        }
        System.out.println(dp[(1<<m)-1]);
    }

}

 

组合数问题

题目描述

给 n,m,kn,m,k,求有多少对 (i,j)(i,j) 满足 1≤i≤n,0≤j≤min⁡(i,m)1≤i≤n,0≤j≤min(i,m)且 (ji)≡0(modk),k(ij​)≡0(modk),k 是质数。其中 (ji)(ij​) 是组合数,表示从 ii 个不同的数中选出 jj 个组成 一个集合的方案数。

输入描述

第一行两个数 t,kt,k,其中 tt 代表该测试点包含 tt 组询问,kk 的意思与上文中相同。

接下来 tt 行每行两个整数 n,mn,m,表示一组询问。

其中,1≤k≤108,1≤t≤105,1≤n,m≤10181≤k≤108,1≤t≤105,1≤n,m≤1018,且 kk 是质数。

输出描述

输出 tt 行,每行一个整数表示对应的答案。由于答案可能很大,请输出答案除以 109+7109+7 的余数。

输入输出样例

示例

输入

1 2
3 3

输出

1
import java.io.*;
import java.util.*;

//这个只能过2个样例,其它都超时了
public class Main {
    static final int MOD = (int)1e9 + 7;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        String[] input = br.readLine().split(" ");
        int t = Integer.parseInt(input[0]);
        long k = Long.parseLong(input[1]);

        while (t-- > 0) {
            input = br.readLine().split(" ");
            long n = Long.parseLong(input[0]);
            long m = Long.parseLong(input[1]);

            long result = countPairs(n, m, k);
            bw.write(result + "\n");
        }

        bw.flush();
        bw.close();
    }

    private static long countPairs(long n, long m, long k) {
        long count = 0;

        for (long i = 1; i <= n; i++) {
            long maxJ = Math.min(i, m);
            for (long j = 0; j <= maxJ; j++) {
                if (lucasTheorem(i, j, k) == 0) {
                    count++;
                }
            }
        }

        return count % MOD;
    }

    private static long lucasTheorem(long n, long m, long p) {
        if (m == 0) return 1;
        return (lucasTheorem(n / p, m / p, p) * comb(n % p, m % p)) % p;
    }

    private static long comb(long n, long k) {
        if (k > n) return 0;
        if (k == 0 || k == n) return 1;
        if (k > n - k) k = n - k;

        long result = 1;
        for (long i = 0; i < k; i++) {
            result = result * (n - i) / (i + 1);
        }

        return result;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值