第二届“传智杯”全国大学生IT技能大赛(初赛)-Java B组题解

A-软件工程实习

A_软件工程实习洛谷链接

题目描述

某大学的《软件工程》必修课分为理论和实践部分。理论部分由该校教授完成授课;而实践部分是由第三方的公司主导,需要同学们在五周时间内自学 HTML、css、JavaScript、vue、Python、django 等技术,并组队完成一个真实的互联网商业应用。

参与这个课程的有 n(0\le n \le 1000)个学生,分成了不超过 26 个队伍,每个队伍用 A 到 Z 来表示。每个队伍都会完成一个项目,并以队伍为单位,给所有队伍(包括自己队伍)打分,范围是 0 到 100 的整数。

为了平息学生对这门课产生的出多问题的不满(比如工作量太大、时间过于紧张、考核方式不公平等),老师决定使用一种“看起来”很公平的方式来决定每组队伍的项目得分:

对于某个队伍,首先计算所有队伍(包括自己)给这个队伍评分的平均值,然后剔除掉和这个平均值差别超过 15 分的评分(保证不会出现所有的评分全部被剔除的情况),最后再对剩余的评分求平均值,四舍五入取整后作为这个队伍的项目得分。

对于每一个同学,我们已经得知他们的队伍代号和理论成绩(也是 0 到 100 分的整数)。这位同学的最后得分就是 60\% 的理论成绩加上 40\% 的所在队伍的项目得分,然后四舍五入取整。

现在老师想知道所有同学的分数排行。请按最后得分从高到低的顺序,输出每位同学的得分和他所在的队伍。

输入格式

第一行两个整数 n 和 k,分别表示学生数和队伍数。

接下来 n 行,每行一个整数 s_i 和一个大写字母 c_i ,表示第 i 个选手的理论分数和队伍编号。保证队伍编号范围是从 A 开始后连续 k 个字母中的一个。

接下来 k 行,每行 k 个整数。其中第 i 行第 j 列的整数 a_{i,j}​ 表示第 i 个队伍给第 j 个队伍的评分,当 i=j 时,就是自评。

输出格式

输出 n 行表示答案,得分高的同学优先输出,得分相同时队伍编号较小的同学优先输出。对于每一行,先输出这位同学成绩,然后输出代表他的队伍编号的大写英文字母。

思路

  1. 定义一个学生类,包含理论分数、团队代号、最终分数三个属性,自定义排序规则将其按照题目要求排序,然后根据题目进行模拟即可。
  2. 根据题目输入数据,然后求每个队伍代号的平均值,在此遍历每个每个队伍代号的成绩,与平均值比较大于15的舍去,计算新的平均值(四舍五入),然后按照题目要求计算各同学的最终成绩(四舍五入),最后排序输出即可。
  3. 题目不难,但一定要细心!

代码

package _传智杯.初赛._2;

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

public class 软件工程实习 {
   static class student implements Comparable<student>{
        public int score;
        public char team;
        public long finalscore;
        public int compareTo(student s){
            if(this.finalscore>s.finalscore)
                return -1;
            else if(this.finalscore==s.finalscore){
                if(this.team<s.team)
                    return -1;
            }
            return 1;
        }
    }
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int k=sc.nextInt();
        student s[]=new student[n];
        int a[][]=new int[k][k];
        double b[]=new double[k];
        for(int i=0;i<n;i++){
            student s1=new student();
            s1.score=sc.nextInt();
            s1.team=sc.next().charAt(0);
            s[i]=s1;
        }
        for(int i=0;i<k;i++){
            for(int j=0;j<k;j++){
                a[i][j]=sc.nextInt();
            }
        }
        for(int j=0;j<k;j++){
            int sum1=0;
            for(int i=0;i<k;i++){
                sum1+=a[i][j];
            }
            double avg1=sum1*1.0/k;
            int sum2=0;
            int y=0;
            for(int i=0;i<k;i++){
                if(a[i][j]>=avg1-15&&a[i][j]<=avg1+15){
                    sum2+=a[i][j];
                    y++;
                }
            }
            double avg2=sum2*1.0/y;
            b[j]=Math.round(avg2);
        }
        for(int i=0;i<s.length;i++){
            double x1=s[i].score*0.6+b[s[i].team-'A']*0.4;
            s[i].finalscore= Math.round(x1);
        }
        Arrays.sort(s);
        for(int i=0;i<n;i++){
            System.out.println(s[i].finalscore+" "+s[i].team);
        }
    }
}

 

B-程序员节发橙子

B_程序员节发橙子洛谷链接

题目描述

每年的 1024 程序员节日,黑马程序员都会举办大型的庆祝活动。今年的程序员节也不例外,每个班级的同学都发了橙子。

班级里有 n 名同学从前到后排成一排,且已经得知了这些同学的成绩,其中第 i 名同学的成绩是 a_i​。班主任想根据同学们上个阶段的考试成绩来评定发橙子的数量。为了激励成绩优秀同学,发橙子时需要满足如下要求:

  • 相邻同学中成绩好的同学的橙子必须更多。若相邻的同学成绩一样,则它们分到的数量必须平等。
  • 每个同学至少分配一个橙子

由于预算有限,班主任希望在符合要求的情况下发出尽可能少的橙子。请问,至少需要准备多少橙子呢?

输入格式

第一行是一个整数 n,表示学生数量。

接下来一行有 n 个整数,第 i 个整数 a_i,表示第 i 个同学的成绩。

输出格式

输出答案,也就是需要最少准备多少个橙子。

输入输出样例

输入 #1

5
3 4 5 4 3

输出 #1

9

说明/提示

样例 1 解释

每位同学拿到的橙子的数量分别是 1,2,3,2,1 所以至少需要准备 9 个。

数据规模与约定

对于全部的测试点,保证 1 \leq n \leq 10^60 \leq a_i \leq 10^9.

思路

这个题一开始想简单了,理解错误,误以为只要分数一样不管相不相邻橙子个数都一样,后来又仔细读了题目才真正理解,大家一定要认真读题!

这个题看了其他佬的题解,总体思路是从前往后、从后往前两次循环,每次循环保证成绩优异者个数更多,相同成绩且相邻的个数相同,最后进行累加即可。

代码:

package _传智杯.初赛._2;

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

public class 程序员节发橙子 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int a[]=new int[n];
        for(int i=0;i<n;i++){
            a[i]=sc.nextInt();
        }
        int b[]=new int[n];
        Arrays.fill(b,1);
        for(int i=0;i<n-1;i++){
            if(a[i+1]>a[i]){
                b[i+1]= Math.max(b[i+1],b[i]+1);
            }
            if(a[i+1]==a[i])
                b[i+1]=b[i];
        }
        for(int i=n-1;i>=1;i--){
            if(a[i-1]>a[i]){
                b[i-1]= Math.max(b[i-1],b[i]+1);
            }
            if(a[i-1]==a[i]){
                b[i-1]=b[i];
            }
        }
        long sum=0;
        for(int i=0;i<n;i++){
            sum+=b[i];
        }
        System.out.println(sum);
    }
}

C-众数出现的次数

C_众数出现的次数洛谷链接

题目描述

传智专修学员的课堂上,为了活跃气氛,并巩固位运算的知识,同学们玩起了一个游戏。

班级里有 n(n\le10^6) 名同学,每位同学都获得了两张卡,红卡或者黑卡。每张卡上都有一个不超过 10^9 的非负整数。第 i 位同学手里红卡数字是 a_i ,黑卡数字是 b_i

现在需要每位同学出牌。每位同学可以直接将红卡上的数字打出,或者将自己的红卡上的数字和自己黑卡数字进行按位异或操作后的结果打出。最后老师会收集所有同学打出的数字。

这些数字中出现次数最多的数字是众数。在所有同学合作的最优策略下,我们希望众数对应数字出现的次数尽可能多。请问出现次数最多的数字是多少呢?

输入格式

第一行,一个正整数 n。

接下来 n 行,其中第 i 行时非负整数 a_i,b_i代表第 i 名同学手上红卡和黑卡的数字。

输出格式

一个整数,表示答案。如果有多个解,请输出最小的那个。

思路:

定义两个数组分别代表红卡和黑卡,由于红卡也直接出而黑卡无法直接出,但可以和红卡异或后再出,因此b数组在初始化时直接与a数组进行异或操作,然后利用map存放出现的数字即次数,遍历map,找出出现次数最多的数字输出即可。

代码:

package _传智杯.初赛._2;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class 众数出现的次数 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int a[]=new int[n];
        int b[]=new int[n];
        for(int i=0;i<n;i++){
            a[i]=sc.nextInt();
            b[i]=a[i]^sc.nextInt();
        }
        Map<Integer,Integer>map=new HashMap<>();
        for(int i=0;i<n;i++){
            if(a[i]!=b[i]){
                if(map.containsKey(a[i])){
                    map.put(a[i],map.get(a[i])+1);
                }
                else {
                    map.put(a[i],1);
                }
                if(map.containsKey(b[i])){
                    map.put(b[i],map.get(b[i])+1);
                }
                else {
                    map.put(b[i],1);
                }
            }
            else {
                if(map.containsKey(a[i])){
                    map.put(a[i],map.get(a[i])+1);
                }
                else {
                    map.put(a[i],1);
                }
            }
        }
        int max=0;
        int res=0;
        for(Map.Entry<Integer,Integer>m:map.entrySet()){
            if(m.getValue()>max){
                max=m.getValue();
                res=m.getKey();
            }
            if(m.getValue()==max&&m.getKey()<res){
                res=m.getKey();
            }
        }
        System.out.println(res);
    }
}

D-特殊的翻转

D_特殊的翻转洛谷链接

题目描述

k 老师在研究一段病毒程序的代码。这段代码是由一段长度不超过 10^6 的十六进制字符(也就是 0 到 9 和 A 到 F)组成的信息。现在 k 老师要将其转换为二进制的 0/1 串(这个时候需要确保最高位是 1)。然后对这个 0/1 串进行“翻转”操作。

对于每次“翻转”操作,k 老师可以选择这个 0/1 串中的其中一位,将这一位和这一位相邻的两位,一共三位,分别进行“翻转”(也就是 0 变 1,1 变 0)。如果指定的这一位是序列的开头或者结尾,那么翻转这一位和存在的相邻位即可。

k 老师想知道,如何用最少的“翻转”步骤,将这个 0/1 串变为全 0 的串。

输入格式

一个十六进制的字符串,由 0 到 9 和 A 到 F 构成。

输出格式

最少能将其变为全 0 串需要的“翻转”步骤次数。如果无论如何都不能将其变为全 0 串,则输出 No

思路:

首先将输入的十六进制数转化为二进制,一位十六进制对应四位二进制数,然后去掉前置0,翻转时需要注意,因为开头时可翻转两位或者三位,因此分两种情况分别计算各翻转次数,若两种情况均无法全部翻转至全0串,则输出No,否则输出两者中较小的结果。

无法翻转至全0串的情况:因为除首位外,每次翻转需要翻转连续的三位,因此前n-2位均可保证全部翻转至全0串。当前n-2位为全0串时,串中最后两位决定能否翻转为全0串,若最后两位全位1,则再翻转一次即可,全位0则无需翻转,10或01则无论如何翻转都无法成为全0串。

输入输出样例

输入 #1

15

输出 #1

3

输入 #2

FF

输出 #2

3

输入 #3

10

输出 #3

No

代码:

package _传智杯.初赛._2;
import java.util.Scanner;

public class 特殊的翻转 {
    public static char[] OtoB(String s){
        StringBuilder s1=new StringBuilder();
        String s2=null;
        for(int i=0;i<s.length();i++){
            if(s.charAt(i)=='0') s1.append("0000");
            if(s.charAt(i)=='1') s1.append("0001");
            if(s.charAt(i)=='2') s1.append("0010");
            if(s.charAt(i)=='3') s1.append("0011");
            if(s.charAt(i)=='4') s1.append("0100");
            if(s.charAt(i)=='5') s1.append("0101");
            if(s.charAt(i)=='6') s1.append("0110");
            if(s.charAt(i)=='7') s1.append("0111");
            if(s.charAt(i)=='8') s1.append("1000");
            if(s.charAt(i)=='9') s1.append("1001");
            if(s.charAt(i)=='A') s1.append("1010");
            if(s.charAt(i)=='B') s1.append("1011");
            if(s.charAt(i)=='C') s1.append("1100");
            if(s.charAt(i)=='D') s1.append("1101");
            if(s.charAt(i)=='E') s1.append("1110");
            if(s.charAt(i)=='F') s1.append("1111");
        }
        for(int i=0;i<s1.length();i++){
            if(s1.charAt(i)=='1'){
                s2=s1.substring(i);
                return s2.toCharArray();
            }
        }
        return s1.toString().toCharArray();
    }
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        String s=sc.next();
        char a[]=OtoB(s);
        char b[]=OtoB(s);
        int n=a.length;
        if(n==1){
            System.out.println(n);
            return;
        }
        int res1=0;
        int res2=0;
        //首次换三位
        for(int i=0;i<n-2;i++){
            if(a[i]=='1'){
                a[i]^=1;
                a[i+1]^=1;
                a[i+2]^=1;
                res1++;
            }
        }
        if(a[n-1]!=a[n-2])
            res1=-1;
        else if(a[n-1]=='1'&&a[n-2]=='1')
            res1++;
        //首次换两位
        for(int i=0;i<n-2;i++){
            if(i==0){
                b[i]^=1;
                b[i+1]^=1;
                res2++;
            }
            else{
                if(b[i]=='1'){
                    b[i]^=1;
                    b[i+1]^=1;
                    b[i+2]^=1;
                    res2++;
                }
            }
        }
        if(b[n-1]!=b[n-2])
            res2=-1;
        else if(b[n-1]=='1'&&b[n-2]=='1')
            res2++;
        //输出
        if(res1==-1||res2==-1){
            if(res1==-1&&res2==-1)
                System.out.println("No");
            else
                System.out.println(Math.max(res1,res2));
        }
        else
            System.out.println(Math.min(res1,res2));
    }
}

有问题可私聊或者评论,看到后会第一时间回复!

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第六届传智杯B初赛是传智播客举办的一次IT技术竞赛的初赛阶段,旨在选拔出各高校优秀的程序设计人才。该比赛中,参赛者将面临多道编程题目,通过编写程序解决问题来展示他们的技术水平和创新能力。 在初赛中,参赛者需要在规定的时间内完成多道程序设计题目。这些题目可能涉及数据结构、算法、网络通信等方面的知识,要求参赛者具备扎实的编程基础和解决实际问题的能力。 参赛者需要在规定的时间内完成编程题目,并提交给评委进行评分。评委会根据答案的正确性、效率、代码的可读性等方面对参赛者的作品进行综合评判。最终,得分高的参赛者将进入下一轮比赛。 第六届传智杯B初赛的目的是为了选拔出具备优秀编程能力的学生,为他们提供一个展示才华、学习交流的平台。参赛者不仅可以通过比赛锻炼自己的编程技巧,还可以结识其他优秀的参赛者,相互学习、切磋技艺。 在比赛过程中,参赛者还可以通过与其他选手交流,了解各种不同的编程思路和解题方法,不断提高自己的编程水平。同时,参赛者还有机会与业界的专家学者进行交流,了解最新的技术动态和发展趋势。 总之,第六届传智杯B初赛是一次很有意义的编程竞赛,为各大高校的IT人才选拔提供了一次难得的机会。通过比赛,参赛者可以展现自己的才华,提升技术水平,同时也可以与其他优秀选手进行交流,共同进步。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值