PAT乙级(81-95题)

1081 检查密码 (15 分)

题目

本题要求你帮助某网站的用户注册模块写一个密码合法性检查的小功能。该网站要求用户设置的密码必须由不少于6个字符组成,并且只能有英文字母、数字和小数点 .,还必须既有字母也有数字。

输入格式:

输入第一行给出一个正整数 N(≤ 100),随后 N 行,每行给出一个用户设置的密码,为不超过 80 个字符的非空字符串,以回车结束。

输出格式:

对每个用户的密码,在一行中输出系统反馈信息,分以下5种:

  • 如果密码合法,输出Your password is wan mei.
  • 如果密码太短,不论合法与否,都输出Your password is tai duan le.
  • 如果密码长度合法,但存在不合法字符,则输出Your password is tai luan le.
  • 如果密码长度合法,但只有字母没有数字,则输出Your password needs shu zi.
  • 如果密码长度合法,但只有数字没有字母,则输出Your password needs zi mu.

输入样例:

5
123s
zheshi.wodepw
1234.5678
WanMei23333
pass*word.6

输出样例:

Your password is tai duan le.
Your password needs shu zi.
Your password needs zi mu.
Your password is wan mei.
Your password is tai luan le.

代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

        int sum = Integer.parseInt(bf.readLine());

        String[] datas = new String[sum];

        for (int i = 0; i < sum; i++) {
            datas[i] = bf.readLine();
        }

        for (int i = 0; i < sum; i++) {
            System.out.println(check(datas[i]));
        }
    }

    private static String check(String pwd) {
        // TODO Auto-generated method stub
        if (pwd.length() < 6)
            return "Your password is tai duan le.";
        
        for (int i = 0; i < pwd.length(); i++) {
            char ch = pwd.charAt(i);
            if (!isVaild(ch))
                return "Your password is tai luan le.";
        }
        
        boolean typeflag1 = false;
        for (int i = 0; i < pwd.length(); i++) {
            char ch = pwd.charAt(i);
            if (ch >= '0' && ch <= '9') {
                typeflag1 = true;
            }
        }
        if(!typeflag1) return "Your password needs shu zi.";
        
        boolean typeflag2 = false;
        for (int i = 0; i < pwd.length(); i++) {
            char ch = pwd.charAt(i);
            if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z') {
                typeflag2 = true;
            }
        }
        if(!typeflag2) return "Your password needs zi mu.";
        
        return "Your password is wan mei.";
    }

    private static boolean isVaild(char ch) {
        // TODO Auto-generated method stub
        if (ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch == '.') {
            return true;
        }
        return false;
    }
}

1082 射击比赛 (20 分)

题目

本题目给出的射击比赛的规则非常简单,谁打的弹洞距离靶心最近,谁就是冠军;谁差得最远,谁就是菜鸟。本题给出一系列弹洞的平面坐标(x,y),请你编写程序找出冠军和菜鸟。我们假设靶心在原点(0,0)。

输入格式:

输入在第一行中给出一个正整数 N(≤ 10 000)。随后 N 行,每行按下列格式给出:

ID x y

其中 ID 是运动员的编号(由 4 位数字组成);xy 是其打出的弹洞的平面坐标(x,y),均为整数,且 0 ≤ |x|, |y| ≤ 100。题目保证每个运动员的编号不重复,且每人只打 1 枪。

输出格式:

输出冠军和菜鸟的编号,中间空 1 格。题目保证他们是唯一的。

输入样例:

3
0001 5 7
1020 -1 3
0233 0 -1

输出样例:

0233 0001

代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

        int sum = Integer.parseInt(bf.readLine());

        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;

        String maxId = null, minId = null;

        for (int i = 0; i < sum; i++) {
            String[] params = bf.readLine().split(" ");

            int result = Integer.parseInt(params[1]) * Integer.parseInt(params[1])
                    + Integer.parseInt(params[2]) * Integer.parseInt(params[2]);
            if (result < min) {
                min = result;
                minId = params[0];
            }
            if (result > max) {
                max = result;
                maxId = params[0];
            }
        }

        System.out.print(minId + " " + maxId);
    }
}

1083 是否存在相等的差 (20 分)

题目

给定 N 张卡片,正面分别写上 1、2、……、N,然后全部翻面,洗牌,在背面分别写上 1、2、……、N。将每张牌的正反两面数字相减(大减小),得到 N 个非负差值,其中是否存在相等的差?

输入格式:

输入第一行给出一个正整数 N(2 ≤ N ≤ 10 000),随后一行给出 1 到 N 的一个洗牌后的排列,第 i 个数表示正面写了 i 的那张卡片背面的数字。

输出格式:

按照“差值 重复次数”的格式从大到小输出重复的差值及其重复的次数,每行输出一个结果。

输入样例:

8
3 5 8 6 2 1 4 7

输出样例:

5 2
3 3
2 2

代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int count = Integer.parseInt(br.readLine());
        String[] params = br.readLine().split(" ");

        int[] datas = new int[count];
        for (int i = 0; i < count; i++) {
            datas[Math.abs(Integer.parseInt(params[i]) - (i + 1))]++;
        }
        for (int i = count - 1; i >= 0; i--) {
            if (datas[i] > 1) {
                System.out.println(i + " " + datas[i]);
            }
        }
    }
}

1084 外观数列 (20 分)

题目

外观数列是指具有以下特点的整数序列:

d, d1, d111, d113, d11231, d112213111, ...

它从不等于 1 的数字 d 开始,序列的第 n+1 项是对第 n 项的描述。比如第 2 项表示第 1 项有 1 个 d,所以就是 d1;第 2 项是 1 个 d(对应 d1)和 1 个 1(对应 11),所以第 3 项就是 d111。又比如第 4 项是 d113,其描述就是 1 个 d,2 个 1,1 个 3,所以下一项就是 d11231。当然这个定义对 d = 1 也成立。本题要求你推算任意给定数字 d 的外观数列的第 N 项。

输入格式:

输入第一行给出 [0,9] 范围内的一个整数 d、以及一个正整数 N(≤ 40),用空格分隔。

输出格式:

在一行中给出数字 d 的外观数列的第 N 项。

输入样例:

1 8

输出样例:

1123123111

代码

#include <iostream>
#include <string>

using namespace std;

string analyse(string str) {
    string out = "";
    for (int i = 0; i < str.length(); i++) {
        out += str[i];
        int count = 1;
        while (i + 1 < str.length() && str[i] == str[i + 1]) {
            i++;
            count++;
        }
        out += to_string(count);
    }
    return out;
}
int main() {
    string d;
    int N;

    cin >> d >> N;

    for (int i = 1; i < N; i++) {
        d = analyse(d);
    }
    cout << d << endl;
}

1085 PAT单位排行 (25 分)

题目

每次 PAT 考试结束后,考试中心都会发布一个考生单位排行榜。本题就请你实现这个功能。

输入格式:

输入第一行给出一个正整数 N(≤105),即考生人数。随后 N 行,每行按下列格式给出一个考生的信息:

准考证号 得分 学校

其中准考证号是由 6 个字符组成的字符串,其首字母表示考试的级别:B代表乙级,A代表甲级,T代表顶级;得分是 [0, 100] 区间内的整数;学校是由不超过 6 个英文字母组成的单位码(大小写无关)。注意:题目保证每个考生的准考证号是不同的。

输出格式:

首先在一行中输出单位个数。随后按以下格式非降序输出单位的排行榜:

排名 学校 加权总分 考生人数

其中排名是该单位的排名(从 1 开始);学校是全部按小写字母输出的单位码;加权总分定义为乙级总分/1.5 + 甲级总分 + 顶级总分*1.5整数部分考生人数是该属于单位的考生的总人数。

学校首先按加权总分排行。如有并列,则应对应相同的排名,并按考生人数升序输出。如果仍然并列,则按单位码的字典序输出。

输入样例:

10
A57908 85 Au
B57908 54 LanX
A37487 60 au
T28374 67 CMU
T32486 24 hypu
A66734 92 cmu
B76378 71 AU
A47780 45 lanx
A72809 100 pku
A03274 45 hypu

输出样例:

5
1 cmu 192 2
1 au 192 3
3 pku 100 1
4 hypu 81 2
4 lanx 81 2

思路

  1. 利用map<string,int>记录是否新添加的记录。map[string]的值等于0,表示新添加记录。否则,map[string]的值-1 等于数组vector<Info>的下标。
  2. 所有记录都存放到vector<Info>后,遍历vector,生产最终成绩。
  3. 排序,输出。

代码

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <cctype>

using namespace std;

struct Info {
    string school;                  //学校简称
    int BGrade, AGrade, TGrade;     //乙、甲、顶级成绩
    int G;                          //最终成绩
    int stuNum;                     //学生人数
};

int cmp(Info a, Info b) {
    if (a.G != b.G) {
        return a.G > b.G;
    }
    if (a.stuNum != b.stuNum) {
        return a.stuNum < b.stuNum;
    }
    return a.school < b.school;
}

int main() {
    int N;
    cin >> N;

    vector<Info> v;
    map<string, int> mmap;

    int cnt = 1;
    cin.sync_with_stdio(false);
    for (int i = 0; i < N; i++) {
        string no;
        int grade;
        string school;

        cin >> no >> grade >> school;
        for (int j = 0; j < school.length(); j++) {
            school[j] = tolower(school[j]);
        }

        char ch = no[0];
        if (ch == 'A') {
            if (mmap[school] != 0) {
                v[mmap[school] - 1].AGrade += grade;
                v[mmap[school] - 1].stuNum++;
            } else {
                v.push_back(Info{ school,0,grade,0,0,1 });
                mmap[school] = cnt++;
            }
        } else if (ch == 'B') {
            if (mmap[school] != 0) {
                v[mmap[school] - 1].BGrade += grade;
                v[mmap[school] - 1].stuNum++;
            } else {
                v.push_back(Info{ school,grade,0,0,0,1 });
                mmap[school] = cnt++;
            }
        } else {
            if (mmap[school] != 0) {
                v[mmap[school] - 1].TGrade += grade;
                v[mmap[school] - 1].stuNum++;
            } else {
                v.push_back(Info{ school,0,0,grade,0,1 });
                mmap[school] = cnt++;
            }
        }
    }

    for (int i = 0; i < v.size(); i++) {
        v[i].G = v[i].BGrade / 1.5 + v[i].AGrade + v[i].TGrade*1.5;
    }
    sort(v.begin(), v.end(), cmp);

    int no = 0;
    cout << v.size() << endl;
    for (int i = 0; i < v.size(); i++) {
        if (!(i - 1 >= 0 && v[i].G == v[i - 1].G)) {
            no = i + 1;
        }
        cout << no << " " << v[i].school << " " << v[i].G << " " << v[i].stuNum << endl;
    }
}

1087 有多少不同的值(20 分)

题目

当自然数 n 依次取 1、2、3、……、N 时,算式 ⌊n/2⌋+⌊n/3⌋+⌊n/5⌋ 有多少个不同的值?(注:⌊x⌋ 为取整函数,表示不超过 x 的最大自然数,即 x 的整数部分。)
输入格式:

输入给出一个正整数 N(2≤N≤10​4​​)。

输出格式:

在一行中输出题面中算式取到的不同值的个数。

输入样例:

2017

输出样例:

1480

注意事项

注意循环的范围。

代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Set;

public class Main {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        int a = Integer.parseInt(bufferedReader.readLine());

        Set<Integer> integers = new HashSet<>();
        for (int i = 1; i <= a; i++) {
            integers.add(i / 2 + i / 3 + i / 5);
        }
        System.out.print(integers.size());
    }
}

1088 三人行 (20 分)

题目

子曰:“三人行,必有我师焉。择其善者而从之,其不善者而改之。”

本题给定甲、乙、丙三个人的能力值关系为:甲的能力值确定是 2 位正整数;把甲的能力值的 2 个数字调换位置就是乙的能力值;甲乙两人能力差是丙的能力值的 X 倍;乙的能力值是丙的 Y 倍。请你指出谁比你强应“从之”,谁比你弱应“改之”。

输入格式:

输入在一行中给出三个数,依次为:M(你自己的能力值)、X 和 Y。三个数字均为不超过 1000 的正整数。

输出格式:

在一行中首先输出甲的能力值,随后依次输出甲、乙、丙三人与你的关系:如果其比你强,输出 Cong;平等则输出 Ping;比你弱则输出 Gai。其间以 1 个空格分隔,行首尾不得有多余空格。

注意:如果解不唯一,则以甲的最大解为准进行判断;如果解不存在,则输出 No Solution

输入样例 1:

48 3 7

输出样例 1:

48 Ping Cong Gai

输入样例 2:

48 11 6

输出样例 2:

No Solution

注意事项

丙的取值不一定是整数,需要用double型

代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] params = br.readLine().split(" ");

        int M = Integer.parseInt(params[0]);
        int X = Integer.parseInt(params[1]);
        int Y = Integer.parseInt(params[2]);

        int JIA = 0, YI = 0;
        double BING = 0;
        boolean isSolve = false;
        for (int i = 10; i < 100; i++) {
            Object[] datas = isSolve(i, X, Y);
            if ((boolean) datas[0] && (int) datas[1] > JIA) {
                JIA = (int) datas[1];
                YI = (int) datas[2];
                BING = (double) datas[3];
                isSolve = true;
            }
        }
        if (isSolve) {
            System.out.print(JIA + " " + getInfo(M, JIA) + " " + getInfo(M, YI) + " " + getInfo(M, BING));
        } else {
            System.out.print("No Solution");
        }
    }

    private static String getInfo(int M, double data) {
        if (M > data) {
            return "Gai";
        } else if (M == data) {
            return "Ping";
        } else {
            return "Cong";
        }
    }

    /*返回有4个参数
    param1:甲为i时能否解决、param2-4:甲乙丙的值*/
    private static Object[] isSolve(int i, int X, int Y) {
        int JIA = i;
        int YI = JIA % 10 * 10 + JIA / 10;
        double BING = 0;

        if (Math.abs(JIA - YI) * Y != YI * X) {
            return new Object[]{false};
        }
        BING = (Math.abs(JIA - YI) * 1.0 / X);
        return new Object[]{true, JIA, YI, BING};
    }
}

1089 狼人杀-简单版 (20 分)

题目

以下文字摘自《灵机一动·好玩的数学》:“狼人杀”游戏分为狼人、好人两大阵营。在一局“狼人杀”游戏中,1 号玩家说:“2 号是狼人”,2 号玩家说:“3 号是好人”,3 号玩家说:“4 号是狼人”,4 号玩家说:“5 号是好人”,5 号玩家说:“4 号是好人”。已知这 5 名玩家中有 2 人扮演狼人角色,有 2 人说的不是实话,有狼人撒谎但并不是所有狼人都在撒谎。扮演狼人角色的是哪两号玩家?

本题是这个问题的升级版:已知 N 名玩家中有 2 人扮演狼人角色,有 2 人说的不是实话,有狼人撒谎但并不是所有狼人都在撒谎。要求你找出扮演狼人角色的是哪几号玩家?

输入格式:

输入在第一行中给出一个正整数 N(5≤N≤100)。随后 N 行,第 i 行给出第 i 号玩家说的话(1≤i≤N),即一个玩家编号,用正号表示好人,负号表示狼人。

输出格式:

如果有解,在一行中按递增顺序输出 2 个狼人的编号,其间以空格分隔,行首尾不得有多余空格。如果解不唯一,则输出最小序列解 —— 即对于两个序列 A=a[1],...,a[M] 和 B=b[1],...,b[M],若存在 0≤k<M 使得 a[i]=b[i] (i≤k),且 a[k+1]<b[k+1],则称序列 A 小于序列 B。若无解则输出 No Solution

输入样例 1:

5
-2
+3
-4
+5
+4

输出样例 1:

1 4

输入样例 2:

6
+6
+3
+1
-5
-2
+4

输出样例 2(解不唯一):

1 5

输入样例 3:

5
-2
-3
-4
-5
-1

输出样例 3:

No Solution

思路

  1. i从1到n遍历,j从i+1到n遍历。在遍历的过程中,假定i和j是狼人,其他人都是好人。
  2. 在i,j遍历的过程中,k从1到n遍历,为了找到此时说谎的人。因为此时狼人与好人的身份已经假定,判断某人是否说谎,只要判断他声称的人的身份与该人实际是身份是否一致即可(正负号是否同号)。
  3. 若说谎的只有两人,且一个人是狼人,一个人是好人,则i,j就是最小解。否则无解。

代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(bf.readLine());
        int[] speak = new int[N + 1];

        for (int i = 1; i <= N; i++) {
            speak[i] = Integer.parseInt(bf.readLine());
        }

        for (int i = 1; i <= N; i++) {
            for (int j = i + 1; j <= N; j++) {
                int[] lie = new int[N];
                //身份数组,-1是狼人,1是好人
                int[] identity = getIdentity(N + 1);
                //假定i和j是狼人
                identity[i] = identity[j] = -1;
                //在假定狼人和好人的情况下,找到说谎的人
                int cnt = 0;
                for (int k = 1; k <= N; k++) {
                    //如果某人说谎,则他说的数字的正负号会和目标人物身份的正负号相反
                    if (speak[k] * identity[Math.abs(speak[k])] < 0) {
                        lie[cnt++] = k;
                    }
                }
                //若说谎的人是两个,且符合一个狼人、一个好人,则i和j就是最小解
                if (cnt == 2 && (identity[lie[0]] + identity[lie[1]] == 0)) {
                    System.out.println(i + " " + j);
                    return;
                }
            }
        }
        System.out.println("No Solution");
    }

    private static int[] getIdentity(int size) {
        int[] result = new int[size + 1];
        for (int i = 1; i <= size; i++) {
            result[i] = 1;
        }
        return result;
    }
}

1090 危险品装箱 (25 分)

题目

集装箱运输货物时,我们必须特别小心,不能把不相容的货物装在一只箱子里。比如氧化剂绝对不能跟易燃液体同箱,否则很容易造成爆炸。

本题给定一张不相容物品的清单,需要你检查每一张集装箱货品清单,判断它们是否能装在同一只箱子里。

输入格式:

输入第一行给出两个正整数:N (≤104) 是成对的不相容物品的对数;M (≤100) 是集装箱货品清单的单数。

随后数据分两大块给出。第一块有 N 行,每行给出一对不相容的物品。第二块有 M 行,每行给出一箱货物的清单,格式如下:

K G[1] G[2] ... G[K]

其中 K (≤1000) 是物品件数,G[i] 是物品的编号。简单起见,每件物品用一个 5 位数的编号代表。两个数字之间用空格分隔。

输出格式:

对每箱货物清单,判断是否可以安全运输。如果没有不相容物品,则在一行中输出 Yes,否则输出 No

输入样例:

6 3
20001 20002
20003 20004
20005 20006
20003 20001
20005 20004
20004 20006
4 00001 20004 00002 20003
5 98823 20002 20003 20006 10010
3 12345 67890 23333

输出样例:

No
Yes
Yes

思路

  1. 这道题与前面那道单身狗很相似,但有不同。相同的地方都是给出一个列表和一个数组,判断是否有匹配/对应危险物。不同点在于本题的一个物品可能有多种危险物,因此需要用map<int,vector<int>>来存储危险物数据,其中map的key为某ID,value为对应危险物的数组。
  2. 在给出一箱货物的清单时,存到list数组的同时,用数组a根据ID标记。最后遍历某ID的危险品数组,若其ID在数组a中也有标记,表明该危险品也在货物清单中,则不能安全运输。

代码

#include <iostream>
#include <map>
#include <vector>

using namespace std;

int main() {
    int N, M;
    cin >> N >> M;

    map<int, vector<int>> mmap;
    for (int i = 0; i < N; i++) {
        int a, b;
        cin >> a >> b;
        mmap[a].push_back(b);
        mmap[b].push_back(a);
    }

    for (int i = 0; i < M; i++) {
        int num;
        cin >> num;

        vector<int> list;
        int a[100000] = { 0 };

        //读入数据
        for (int i = 0; i < num; i++) {
            int tmp;
            cin >> tmp;
            list.push_back(tmp);
            a[tmp] = 1;
        }

        //分析数据
        bool isDangerFlag = false;
        for (int i = 0; i < list.size(); i++) {
            for (int j = 0; j < mmap[list[i]].size(); j++) {
                if (a[mmap[list[i]][j]] == 1) {
                    isDangerFlag = true;
                    break;
                }
            }
            if (isDangerFlag) {
                break;
            }
        }
        if (!isDangerFlag) {
            cout << "Yes" << endl;
        } else {
            cout << "No" << endl;
        }
    }
}

1091 N-自守数 (15 分)

题目

如果某个数 K 的平方乘以 N 以后,结果的末尾几位数等于 K,那么就称这个数为“N-自守数”。例如 3×922=25392,而 25392 的末尾两位正好是 92,所以 92 是一个 3-自守数。

本题就请你编写程序判断一个给定的数字是否关于某个 N 是 N-自守数。

输入格式:

输入在第一行中给出正整数 M(≤20),随后一行给出 M 个待检测的、不超过 1000 的正整数。

输出格式:

对每个需要检测的数字,如果它是 N-自守数就在一行中输出最小的 N 和 NK2 的值,以一个空格隔开;否则输出 No。注意题目保证 N<10。

输入样例:

3
92 5 233

输出样例:

3 25392
1 25
No

代码

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner scanner = new Scanner(System.in);
        int a = scanner.nextInt();
        int[] nums = new int[a];

        for (int i = 0; i < a; i++) {
            nums[i] = scanner.nextInt();
        }

        String out = "";
        for (int i = 0; i < nums.length; i++) {
            Object[] params = check(nums[i]);
            if (!(Boolean) params[0]) {
                out += "No" + "\n";
            } else {
                out += params[1] + " " + params[2] + "\n";
            }
        }
        System.out.print(out);
    }

    public static Object[] check(int num) {
        for (int i = 1; i < 10; i++) {
            int result = i * num * num;
            if ((result + "").endsWith(num + "")) {
                return new Object[] { true, i, result };
            }
        }
        return new Object[] { false };
    }
}

1092 最好吃的月饼 (20 分)

题目

月饼是久负盛名的中国传统糕点之一,自唐朝以来,已经发展出几百品种。

3240261-3f4089b57ff3b553.jpg

若想评比出一种“最好吃”的月饼,那势必在吃货界引发一场腥风血雨…… 在这里我们用数字说话,给出全国各地各种月饼的销量,要求你从中找出销量冠军,认定为最好吃的月饼。

输入格式:

输入首先给出两个正整数 N(≤1000)和 M(≤100),分别为月饼的种类数(于是默认月饼种类从 1 到 N 编号)和参与统计的城市数量。

接下来 M 行,每行给出 N 个非负整数(均不超过 1 百万),其中第 i 个整数为第 i 种月饼的销量(块)。数字间以空格分隔。

输出格式:

在第一行中输出最大销量,第二行输出销量最大的月饼的种类编号。如果冠军不唯一,则按编号递增顺序输出并列冠军。数字间以 1 个空格分隔,行首尾不得有多余空格。

输入样例:

5 3
1001 992 0 233 6
8 0 2018 0 2008
36 18 0 1024 4

输出样例:

2018
3 5

代码

#include <iostream>

using namespace std;

int main() {

    int N, M;
    cin >> N >> M;

    int A[1001] = { 0 };
    int tmp;
    int max = 0, maxIndex = 0;

    for (size_t i = 0; i < M*N; i++) {
        cin >> tmp;
        A[i%N] += tmp;
        if (A[i%N] > max) {
            max = A[i%N];
            maxIndex = i % N;
        }
    }
    cout << max << endl;

    int count = 0;
    for (size_t i = 0; i < N; i++) {
        if (A[i] == max) {
            if (count == 0) {
                printf("%d", i + 1);
            } else {
                printf(" %d", i + 1);
            }
            count++;
        }
    }
}

1093 字符串A+B (20 分)

题目

给定两个字符串 A 和 B,本题要求你输出 A+B,即两个字符串的并集。要求先输出 A,再输出 B,但重复的字符必须被剔除

输入格式:

输入在两行中分别给出 A 和 B,均为长度不超过 106的、由可见 ASCII 字符 (即码值为32~126)和空格组成的、由回车标识结束的非空字符串。

输出格式:

在一行中输出题面要求的 A 和 B 的和。

输入样例:

This is a sample test
to show you_How it works

输出样例:

This ampletowyu_Hrk

代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

        String str1 = bf.readLine();
        String str2 = bf.readLine();

        boolean[] flags = new boolean[126 - 32 + 1];
        String out = "";

        for (int i = 0; i < str1.length(); i++) {
            char ch = str1.charAt(i);
            if (flags[ch - 32] == false) {
                out += ch;
                flags[ch - 32] = true;
            }
        }
        for (int i = 0; i < str2.length(); i++) {
            char ch = str2.charAt(i);
            if (flags[ch - 32] == false) {
                out += ch;
                flags[ch - 32] = true;
            }
        }

        System.out.print(out);
    }
}

1094 谷歌的招聘 (20 分)

题目

2004 年 7 月,谷歌在硅谷的 101 号公路边竖立了一块巨大的广告牌(如下图)用于招聘。内容超级简单,就是一个以 .com 结尾的网址,而前面的网址是一个 10 位素数,这个素数是自然常数 e 中最早出现的 10 位连续数字。能找出这个素数的人,就可以通过访问谷歌的这个网站进入招聘流程的下一步。

3240261-9d7c617feeeda7d1.jpg

自然常数 e 是一个著名的超越数,前面若干位写出来是这样的:e = 2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427427466391932003059921... 其中粗体标出的 10 位数就是答案。

本题要求你编程解决一个更通用的问题:从任一给定的长度为 L 的数字中,找出最早出现的 K 位连续数字所组成的素数。

输入格式:

输入在第一行给出 2 个正整数,分别是 L(不超过 1000 的正整数,为数字长度)和 K(小于 10 的正整数)。接下来一行给出一个长度为 L 的正整数 N。

输出格式:

在一行中输出 N 中最早出现的 K 位连续数字所组成的素数。如果这样的素数不存在,则输出 404。注意,原始数字中的前导零也计算在位数之内。例如在 200236 中找 4 位素数,0023 算是解;但第一位 2 不能被当成 0002 输出,因为在原始数字中不存在这个 2 的前导零。

输入样例 1:

20 5
23654987725541023819

输出样例 1:

49877

输入样例 2:

10 3
2468024680

输出样例 2:

404

代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int key = Integer.parseInt(br.readLine().split(" ")[1]);
        String str = br.readLine();

        boolean flag = false;
        for (int i = 0; i + key <= str.length(); i++) {
            String sub = str.substring(i, i + key);
            if (isPrime(sub)) {
                flag = true;
                System.out.print(sub);
                break;
            }
        }
        if (!flag) {
            System.out.print("404");
        }
    }

    private static boolean isPrime(String sub) {
        // TODO Auto-generated method stub
        long num = Long.parseLong(sub);
        if (num == 1) {
            return false;
        }

        if (num == 2) {
            return true;
        }
        for (int i = 2; i <= Math.sqrt(num); i++) {
            if (num % i == 0) {
                return false;
            }
        }
        return true;
    }
}

1095 解码PAT准考证 (25 分)

题目

PAT 准考证号由 4 部分组成:

  • 第 1 位是级别,即 T 代表顶级;A 代表甲级;B 代表乙级;
  • 第 2~4 位是考场编号,范围从 101 到 999;
  • 第 5~10 位是考试日期,格式为年、月、日顺次各占 2 位;
  • 最后 11~13 位是考生编号,范围从 000 到 999。

现给定一系列考生的准考证号和他们的成绩,请你按照要求输出各种统计信息。

输入格式:

输入首先在一行中给出两个正整数 N(≤104)和 M(≤100),分别为考生人数和统计要求的个数。

接下来 N 行,每行给出一个考生的准考证号和其分数(在区间 [0,100] 内的整数),其间以空格分隔。

考生信息之后,再给出 M 行,每行给出一个统计要求,格式为:类型 指令,其中

  • 类型 为 1 表示要求按分数非升序输出某个指定级别的考生的成绩,对应的 指令 则给出代表指定级别的字母;
  • 类型 为 2 表示要求将某指定考场的考生人数和总分统计输出,对应的 指令 则给出指定考场的编号;
  • 类型 为 3 表示要求将某指定日期的考生人数分考场统计输出,对应的 指令 则给出指定日期,格式与准考证上日期相同。

输出格式:

对每项统计要求,首先在一行中输出 Case #: 要求,其中 # 是该项要求的编号,从 1 开始;要求 即复制输入给出的要求。随后输出相应的统计结果:

  • 类型 为 1 的指令,输出格式与输入的考生信息格式相同,即 准考证号 成绩。对于分数并列的考生,按其准考证号的字典序递增输出(题目保证无重复准考证号);
  • 类型 为 2 的指令,按 人数 总分 的格式输出;
  • 类型 为 3 的指令,输出按人数非递增顺序,格式为 考场编号 总人数。若人数并列则按考场编号递增顺序输出。

如果查询结果为空,则输出 NA

输入样例:

8 4
B123180908127 99
B102180908003 86
A112180318002 98
T107150310127 62
A107180908108 100
T123180908010 78
B112160918035 88
A107180908021 98
1 A
2 107
3 180908
2 999

输出样例:

Case 1: 1 A
A107180908108 100
A107180908021 98
A112180318002 98
Case 2: 2 107
3 260
Case 3: 3 180908
107 2
123 2
102 1
Case 4: 2 999
NA

思路

  1. 将准考证与成绩用结构体Info存储,将指令信息用结构体OrderInfo存储。
  2. 按照等级查询,枚举选取匹配的学生,然后排序即可。
  3. 按照考场查询,枚举选取匹配的学生,然后计数、求和。
  4. 按日期查询每个考场人数,用unordered_map存储,最后排序汇总。

注意事项

  1. 处理指令3时,用map会超时,改用unordered_map。
  2. 排序传参用引用传参,这样更快。

代码

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <unordered_map>

using namespace std;

struct Info {
    string no;
    int grade;
};

struct OrderInfo {
    int type;
    string order;
    string result;
};

string fun(int type, vector<Info> v, string order);
int cmp1(Info &a, Info &b);
int cmp2(pair<string, int> &a, pair<string, int> &b);

int main() {
    int N, M;
    cin >> N >> M;

    vector<Info> v1;
    vector<OrderInfo> v2;

    for (int i = 0; i < N; i++) {
        string no;
        int grade;
        cin >> no >> grade;
        v1.push_back(Info{ no,grade });
    }

    for (int i = 0; i < M; i++) {
        int type;
        string order;
        cin >> type >> order;

        string result = fun(type, v1, order);
        v2.push_back(OrderInfo{ type,order,result });
    }

    for (int i = 0; i < v2.size(); i++) {
        printf("Case %d: %d %s\n", i + 1, v2[i].type, v2[i].order.c_str());
        cout << v2[i].result;
    }
}

int cmp1(Info &a, Info &b) {
    return a.grade != b.grade ? a.grade > b.grade:a.no < b.no;
}

int cmp2(pair<string, int> &a, pair<string, int> &b) {
    return a.second != b.second ? a.second > b.second : a.first < b.first;
}

string fun(int type, vector<Info> v, string order) {
    string str;
    if (type == 1) {
        vector<Info> result;
        char ch = order[0];
        for (int i = 0; i < v.size(); i++) {
            if (v[i].no[0] == ch) {
                result.push_back(v[i]);
            }
        }
        if (result.size() == 0) {
            str += "NA\n";
        } else {
            sort(result.begin(), result.end(), cmp1);
            for (int i = 0; i < result.size(); i++) {
                str += result[i].no + " " + to_string(result[i].grade) + "\n";
            }
        }

    } else if (type == 2) {
        int num = 0, sum = 0;
        for (int i = 0; i < v.size(); i++) {
            if (v[i].no.substr(1, 3) == order) {
                num++;
                sum += v[i].grade;
            }
        }
        if (num == 0 && sum == 0) {
            str += "NA\n";
        } else {
            str += to_string(num) + " " + to_string(sum) + "\n";
        }
    } else {
        unordered_map<string, int> mmap;

        for (int i = 0; i < v.size(); i++) {
            if (v[i].no.substr(4, 6) == order) {
                mmap[v[i].no.substr(1, 3)]++;
            }
        }
        if (mmap.size() == 0) {
            str += "NA\n";
        } else {
            vector<pair<string, int>> vec(mmap.begin(), mmap.end());
            sort(vec.begin(), vec.end(), cmp2);
            for (int i = 0; i < vec.size(); i++) {
                str += vec[i].first + " " + to_string(vec[i].second) + "\n";
            }
        }
    }
    return str;
}

猜你喜欢

转载自blog.csdn.net/weixin_33875564/article/details/87205976