第十二届蓝桥杯软件类第二场省赛B组真题题解

题目结构

题目类型分值
第一题结果填空5分
第二题结果填空5分
第三题结果填空10分
第四题结果填空10分
第五题结果填空15分
第六题程序设计15分
第七题程序设计20分
第八题程序设计20分
第九题程序设计25分
第十题程序设计25分

第一题 求余

  • 题面

    在 C/C++/Java/Python 等语言中,使用 % 表示求余,请问 2021%20 的值是多少?

  • 解题思路

    直接输出即可。

  • 答案

    1 1 1


第二题 双阶乘

  • 题面

    一个正整数的双阶乘,表示不超过这个正整数且与它有相同奇偶性的所有 正整数乘积。n 的双阶乘用 n!! 表示。

    例如:

    3!! = 3 × 1 = 3。

    8!! = 8 × 6 × 4 × 2 = 384。

    11!! = 11 × 9 × 7 × 5 × 3 × 1 = 10395。

    请问,2021!! 的最后 5 位(这里指十进制位)是多少? 注意:2021!! = 2021 × 2019 × · · · × 5 × 3 × 1。

    提示:建议使用计算机编程解决问题。

  • 解题思路

    我们需要知道后五位的贡献实际上是和后五位之前的数是没有关系的,所以我们每次在求双阶乘的过程中即是对结果变量取余得到后五位即可。

  • 代码

/**
  *@filename:B
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-05-09 15:58
**/
public class B{
    public static void main(String[] args){
        int cnt=1;
        for(int i=1;i<=2021;i+=2){
            cnt=cnt*i;
            cnt=cnt%100000;
        }
        System.out.println(cnt);//59375.
    }
}
  • 答案

    59375 59375 59375


第三题 格点

  • 题面

    如果一个点 (x, y) 的两维坐标都是整数,即 x ∈ Z 且 y ∈ Z,则称这个点为一个格点。

    如果一个点 (x, y) 的两维坐标都是正数,即 x > 0 且 y > 0,则称这个点在第一象限。

    请问在第一象限的格点中,有多少个点 (x, y) 的两维坐标乘积不超过 2021, 即 x · y ≤ 2021。

    提示:建议使用计算机编程解决问题。

  • 解题思路

    双层 f o r for for循环枚举 ( x , y ) (x,y) (x,y),统计符合条件的点。

  • 代码

/**
  *@filename:C
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-05-09 16:02
**/
public class C{
    public static void main(String[] args){
        int cnt=0;
        for(int x=1;x<=2021;x++){
            for(int y=1;x*y<=2021;y++){
                cnt++;
            }
        }
        System.out.println(cnt);//15698
    }
}
  • 答案

    15698 15698 15698

第四题 整数分解

  • 题面

    将 3 分解成两个正整数的和,有两种分解方法,分别是 3 = 1 + 2 和3 = 2 + 1。注意顺序不同算不同的方法。

    将 5 分解成三个正整数的和,有 6 种分解方法,它们是 1+1+3 = 1+2+2 = 1 + 3 + 1 = 2 + 1 + 2 = 2 + 2 + 1 = 3 + 1 + 1。

    请问,将 2021 分解成五个正整数的和,有多少种分解方法?

  • 解题思路

    这道题其实只要开 3 3 3 f o r for for循环枚举 3 3 3个正整数即可,因为最后得到的值我们就可以知道结果,倘若最后剩余分配的值为 m m m,那实际上就是有 m − 1 m-1 m1种分配方案。累加方案数即可。

  • 代码

/**
  *@filename:D
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-05-09 16:04
**/
import java.util.Arrays;
public class D{
    public static void main(String[] args){
        long cnt=0;
        for(int i=1;i<2021;i++){
            for(int j=1;i+j<2021;j++){
                for(int k=1;i+j+k<2021;k++){
                    int m=2021-i-j-k;
                    if(m<=1)break;
                    cnt+=m-1;
                }
            }
        }
        System.out.println(cnt);//691677274345
    }
}
  • 答案

    691677274345 691677274345 691677274345

第五题 城邦

  • 题面

    小蓝国是一个水上王国,有 2021 个城邦,依次编号 1 到 2021。在任意两个城邦之间,都有一座桥直接连接。

    为了庆祝小蓝国的传统节日,小蓝国政府准备将一部分桥装饰起来。

    对于编号为 ab 的两个城邦,它们之间的桥如果要装饰起来,需要的费用如下计算:找到 ab 在十进制下所有不同的数位,将数位上的数字求和。例如,编号为 2021 和 922 两个城邦之间,千位、百位和个位都不同,将这

    些数位上的数字加起来是 (2 + 0 + 1) + (0 + 9 + 2) = 14。注意 922 没有千位,千

    位看成 0。

    为了节约开支,小蓝国政府准备只装饰 2020 座桥,并且要保证从任意一个城邦到任意另一个城邦之间可以完全只通过装饰的桥到达。

    请问,小蓝国政府至少要花多少费用才能完成装饰。 提示:建议使用计算机编程解决问题。

  • 解题思路

    最小生成树模板题,此题我采用 K r u s k a l Kruskal Kruskal算法实现。

  • 代码

/**
  *@filename:E
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-05-09 16:47
**/
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
public class E{
    public static void main(String[] args){
        Graph graph = new Graph();
        graph.Kruskal();
    }
}
class Graph{
    Edge[] edges = new Edge[2022*2020];
    int[] father = new int[2022];
    int len;
    public int cal(int u,int v){
        int cnt=0;
        while(u>0||v>0){
            if(u%10!=v%10){
                cnt=cnt+u%10+v%10;
            }
            u/=10;
            v/=10;
        }
        return cnt;
    }
    public void init(){
        len=0;
        for(int i=1;i<=2021;i++){
            for(int j=i+1;j<=2021;j++){
                edges[len]=new Edge();
                edges[len].u=i;
                edges[len].v=j;
                edges[len].w=cal(i,j);
                len++;
            }
        }
        for(int i=1;i<=2021;i++)father[i]=i;
    }
    public int find(int x){
        int r=x;
        while(r!=father[r])r=father[r];
        int i=x,j;
        while(father[i]!=r){
            j=father[i];
            father[i]=r;
            i=j;
        }
        return r;
    }
    public void Kruskal(){
        init();
        Arrays.sort(edges,0,len,new Comparator<Edge>(){
            @Override
            public int compare(Edge s1,Edge s2){
                if(s1.w<s2.w)return -1;
                else if(s1.w==s2.w)return 0;
                else return 1;
            }
        });
        System.out.println(edges[0].w);
        int ans=0;
        int fu,fv;
        for(int i=0;i<len;i++){
            fu=find(edges[i].u);
            fv=find(edges[i].v);
            if(fu!=fv){
                father[fu]=fv;
                ans+=edges[i].w;
            }
        }
        System.out.println(ans);//4046
    }
}
class Edge{
    int u,v,w;
    Edge(){
        this.w=0;
    }
    Edge(Edge A){
        this.u=A.u;
        this.v=A.v;
        this.w=A.w;
    }
}
  • 答案

    4046 4046 4046


第六题 特殊年份

  • 题面

    今年是 2021 年,2021 这个数字非常特殊,它的千位和十位相等,个位比百位大 1,我们称满足这样条件的年份为特殊年份。

    输入 5 个年份,请计算这里面有多少个特殊年份。

    【输入格式】

    输入 5 行,每行一个 4 位十进制数(数值范围为 1000 至 9999),表示一个年份。

    【输出格式】

    输出一个整数,表示输入的 5 个年份中有多少个特殊年份。

    【样例输入】

    2019

    2021

    1920

    2120

    9899

    【样例输出】

    2

    【样例说明】

    2021 和 9899 是特殊年份,其它不是特殊年份。

  • 解题思路

    直接判断即可,转化为字符串利用下标索引值判断。

  • 代码

/**
  *@filename:F
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-05-09 21:58
**/
import java.util.*;
public class F{
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);
        Work work =new Work();
        int cnt=0;
        for(int i=0;i<5;i++){
            work.a[i]=input.nextInt();
            if(work.check(work.a[i]))cnt++;
        }
        System.out.println(cnt);
    }
}
class Work{
    public int[] a;
    Work(){
        a = new int[5];
    }
    public boolean check(int year){
      String s = String.valueOf(year);
      if(s.charAt(0)==s.charAt(2)&&s.charAt(3)==s.charAt(1)+1)
          return true;
      else{
          return false;
      }
    }
}

第七题 小平方

  • 题面

    小蓝发现,对于一个正整数 n 和一个小于 n 的正整数 v,将 v 平方后对 n

    取余可能小于 n 的一半,也可能大于等于 n 的一半。

    请问,在 1 到 n − 1 中,有多少个数平方后除以 n 的余数小于 n 的一半。例如,当 n = 4 时,1, 2, 3 的平方除以 4 的余数都小于 4 的一半。

    又如,当 n = 5 时,1, 4 的平方除以 5 的余数都是 1,小于 5 的一半。而

    2, 3 的平方除以 5 的余数都是 4,大于等于 5 的一半。

    【输入格式】

    输入一行包含一个整数 n

    【输出格式】

    输出一个整数,表示满足条件的数的数量。

    【样例输入】

    5

    【样例输出】

    2

    【评测用例规模与约定】

    对于所有评测用例,1 ≤ n ≤ 10000。

  • 解题思路

    枚举判断统计即可。

  • 代码

/**
  *@filename:G
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-05-10 13:52
**/
import java.util.*;
public class G{
    public static void main(String[] args){
        int n;
        Scanner input = new Scanner(System.in);
        n = input.nextInt();
        int ans=0;
        for(int i=1;i<n;i++){
            if(i*i%n*2<n){
                ans++;
            }
        }
        System.out.println(ans);
    }
}

第八题 完全平方数

  • 题面

    一个整数 a 是一个完全平方数,是指它是某一个整数的平方,即存在一个整数 b,使得 a = b2。

    给定一个正整数 n,请找到最小的正整数 x,使得它们的乘积是一个完全平方数。

    【输入格式】

    输入一行包含一个正整数 n

    【输出格式】

    输出找到的最小的正整数 x

    【样例输入 1

    12

    【样例输出 1

    3

    【样例输入 2

    15

    【样例输出 2

    15

    【评测用例规模与约定】

    对于 30% 的评测用例, 1 ≤ n ≤ 1000 1 ≤ n ≤ 1000 1n1000,答案不超过 1000。

    对于 60% 的评测用例, 1 ≤ n ≤ 1 0 8 1 ≤ n≤ 10^8 1n108,答案不超过 1 0 8 10^8 108

    对于所有评测用例, 1 ≤ n ≤ 1012 1 ≤ n≤ 1012 1n1012,答案不超过 1 0 1 2 10^12 1012

  • 解题思路

    凑完全平方数,实际上就是让凑成的数因子都成对。这样才能两两组合。所以我们只需要对 n n n质因数分解得到因子的数量即可,最后根据因子的数量奇偶性分配最少的 x x x即可。具体看代码。

  • 代码

/**
  *@filename:H
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-05-10 13:55
**/
import java.util.Scanner;
import java.util.Collections;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
public class H{
    public static void main(String[] args) {
        Work work =new Work();
        Scanner input = new Scanner(System.in);
        work.n = input.nextLong();
        work.solve();
    }
}
class Work{
    Map p;
    long n;
    Work(){
        p = new HashMap();
    }
    public void cal(){
        for(long i=2;i*i<=n;i++){
            while(n%i==0){
                if(p.containsKey(i)){
                    p.replace(i,(long)p.get(i)+1);
                }
                else{
                    p.put(i,(long)1); 
                }
                n/=i;
            }
        }
        if(n!=1){
            if(p.containsKey(n)){
                p.replace(n,(long)p.get(n)+1);
            }
            else{
                p.put(n,(long)1); 
            }
        }
    }
    public void solve(){
        cal();
        long ans=1;
        Iterator iter = p.entrySet().iterator();
        while(iter.hasNext()){
            Map.Entry entry = (Map.Entry)iter.next();
            long key = (long)entry.getKey();
            long value = (long)entry.getValue();
            if(value%2==1)ans*=key;
            //System.out.println(key+" "+value);
        }
        System.out.println(ans);
    }
}

第九题 负载均衡

  • 题面

    n 台计算机,第 i 台计算机的运算能力为 vi

    有一系列的任务被指派到各个计算机上,第 i 个任务在 ai 时刻分配,指定计算机编号为 bi ,耗时为 ci 且算力消耗为 di 。如果此任务成功分配,将立刻开始运行,期间持续占用 bi 号计算机 di 的算力,持续 ci 秒。

    对于每次任务分配,如果计算机剩余的运算能力不足则输出 −1,并取消这次分配,否则输出分配完这个任务后这台计算机的剩余运算能力。

    【输入格式】

    输入的第一行包含两个整数 n, m,分别表示计算机数目和要分配的任务数。第二行包含 n 个整数 v1, v2, · · · vn,分别表示每个计算机的运算能力。

    接下来 m 行每行 4 个整数 ai, bi, ci, di,意义如上所述。数据保证 ai 严格递增,即 ai < ai+1。

    【输出格式】

    输出 m 行,每行包含一个数,对应每次任务分配的结果。

    【样例输入】

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

    【样例输出】

    2

    -1

    -1

    1

    -1

    0

    【样例说明】

    时刻 1,第 1 个任务被分配到第 1 台计算机,耗时为 5 ,这个任务时刻 6

    会结束,占用计算机 1 的算力 3。

    时刻 2,第 2 个任务需要的算力不足,所以分配失败了。

    时刻 3,第 1 个计算机仍然正在计算第 1 个任务,剩余算力不足 3,所以失败。

    时刻 4,第 1 个计算机仍然正在计算第 1 个任务,但剩余算力足够,分配后剩余算力 1。

    时刻 5,第 1 个计算机仍然正在计算第 1, 4 个任务,剩余算力不足 4,失败。

    时刻 6,第 1 个计算机仍然正在计算第 4 个任务,剩余算力足够,且恰好用完。

    【评测用例规模与约定】

    对于 20% 的评测用例,n, m ≤ 200。对于 40% 的评测用例,n, m ≤ 2000。

    对于所有评测用例, 1 ≤ n , m ≤ 200000 , 1 ≤ a i , c i , d i , v i ≤ 1 0 9 , 1 ≤ b i ≤ n 1 ≤ n, m ≤ 200000,1 ≤ a_i, c_i, d_i, v_i ≤ 10^9,1 ≤ b_i ≤ n 1n,m2000001ai,ci,di,vi1091bin

  • 解题思路

    模拟题。之后补上。

  • 代码

第十题 国际象棋

  • 题面

    众所周知,“八皇后” 问题是求解在国际象棋棋盘上摆放 8 个皇后,使得两两之间互不攻击的方案数。已经学习了很多算法的小蓝觉得 “八皇后” 问题太简单了,意犹未尽。作为一个国际象棋迷,他想研究在 N × M 的棋盘上,摆放 K 个马,使得两两之间互不攻击有多少种摆放方案。由于方案数可能很大,只需 计算答案除以 1000000007 (即 109 + 7) 的余数。

    如下图所示,国际象棋中的马摆放在棋盘的方格内,走 “日” 字,位于 (x, y) 格的马(第 x 行第 y 列)可以攻击 (x + 1, y + 2)、(x + 1, y − 2)、(x − 1, y + 2)、(x − 1, y − 2)、(x + 2, y + 1)、(x + 2, y − 1)、(x − 2, y + 1) 和 (x − 2, y − 1) 共 8 个格子。

    img

    【输入格式】

    输入一行包含三个正整数 N, M, K,分别表示棋盘的行数、列数和马的个数。

    【输出格式】

    输出一个整数,表示摆放的方案数除以 1000000007 (即 109 + 7) 的余数。

    【样例输入】

    1 2 1

    【样例输出】

    2

    【样例输入】

    4 4 3

    【样例输出】

    276

    【样例输入】

    3 20 12

    【样例输出】

    914051446

    【评测用例规模与约定】

    对于 5% 的评测用例,K = 1;

    对于另外 10% 的评测用例,K = 2; 对于另外 10% 的评测用例,N = 1;

    对于另外 20% 的评测用例,N, M ≤ 6,K ≤ 5;

    对于另外 25% 的评测用例,N ≤ 3,M ≤ 20,K ≤ 12;

    对于所有评测用例,1 ≤ N ≤ 6,1 ≤ M ≤ 100,1 ≤ K ≤ 20。

  • 解题思路

    待补。

  • 代码

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

HeZephyr

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

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

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

打赏作者

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

抵扣说明:

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

余额充值