蓝桥杯 2022年省赛真题
Java 大学B组
艹,省赛梦游赛区第一丢了,
吃完午饭出食堂伞也被偷了,
我 r 你哥。
试题 A: 星期计算
本题总分: 5 5 5 分
【问题描述】
已知今天是星期六,请问 2 0 22 20^{22} 2022 天后是星期几?
注意用数字 1 1 1 到 7 7 7 表示星期一到星期日。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
7
快速幂求出 2 0 22 20^{22} 2022 模 7 7 7 的余数就行,它的意义为 2 0 22 20^{22} 2022 天后是某个星期六后的第几天。
用 BigInteger
累乘或者换 P y t h o n \mathrm{Python} Python 上阵都可以,
但作为签到题,其门槛比 C B \mathrm{CB} CB 组别的要高,
我是不大能理解的。
public class Test {
public static void main(String[] args) {
new Test().run(); }
int offset = 1, a = 20, b = 22, p = 7;
void run() {
while (b > 0) {
if (b % 2 == 1)
offset = offset * a % p;
a = a * a % p;
b /= 2;
}
System.out.print(6 + offset);
}
}
试题 B: 山
本题总分: 5 5 5 分
【问题描述】
这天小明正在学数数。
他突然发现有些正整数的形状像一座“山”,比如 123565321 123565321 123565321、 145541 145541 145541,它们左右对称(回文)且数位上的数字先单调不减,后单调不增。
小明数了很久也没有数完,他想让你告诉他在区间 [ [ [ 2022 2022 2022 , , , 2022222022 2022222022 2022222022 ] ] ] 中有多少个数的形状像一座“山”。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
3138
任意一个字串 S S S,都能唯一确定两个回文串 S S ‾ S\ \overline S S S、 S S [ 1 , ∣ S ∣ − 1 ] ‾ S\ \overline{S[1,|S|-1]} S S[1,∣S∣−1],其中 S ‾ \overline S S 表示对 S S S 翻转, S [ i , j ] S[i,j] S[i,j] 表示从 [ i , j ] [i,j] [i,j] 的字符构成的子串。
例如 A B C \mathrm{ABC} ABC 就能确定出 A B C C B A \mathrm{ABCCBA} ABCCBA、 A B C B A \mathrm{ABCBA} ABCBA。
设 f i , j f_{i,j} fi,j 为 [ i , j ] [i,j] [i,j] 中满足题目所述条件的数字个数,将 f 2021 , 2022222022 f_{2021,2022222022} f2021,2022222022 拆分为表达式 f 1 , 1999999999 + f 2000000000 , 2022222022 − f 1 , 2021 − 1 f_{1,1999999999} + f_{2000000000, 2022222022}-f_{1,2021-1} f1,1999999999+f2000000000,2022222022−f1,2021−1。
将第一项 f 1 , 1999999999 f_{1,1999999999} f1,1999999999 用上述性质计算,其余两项暴力求解,即可在一个理想的时间内计算出答案。
public class Test {
public static void main(String[] args) {
new Test().run(); }
int ans = 0, start = 2022, end = 2022222022;
void run() {
for (int i = 1; i < 100000; ++i)
if (check2(i)) {
if (i <= 20000) ++ans;
++ans;
}
System.out.println(ans + calc(2000000000, end) - calc(1, start - 1));
}
int calc(int start, int end) {
int cnt = 0;
while (start <= end)
if (check1(start++)) ++cnt;
return cnt;
}
int[] buff = new int[64];
boolean check1(int k) {
int n = 0;
for (; k > 0; k /= 10)
buff[n++] = k % 10;
buff[n] = 0;
for (int i = n - 1, j = 0; i >= j; --i, ++j)
if (buff[i + 1] > buff[i] || buff[i] != buff[j]) return false;
return true;
}
boolean check2(int k) {
int n = 0;
for (; k > 0; k /= 10)
buff[n++] = k % 10;
buff[n] = 0;
for (int i = n - 1; i >= 0; --i)
if (buff[i + 1] > buff[i]) return false;
return true;
}
}
试题 C: 字符统计
时间限制: 1.0 s 1.0\mathrm s 1.0s 内存限制: 512.0 M B 512.0\mathrm{MB} 512.0MB 本题总分: 10 10 10 分
【问题描述】
给定一个只包含大写字母的字符串 S S S,请你输出其中出现次数最多的字母。
如果有多个字母均出现了最多次,按字母表顺序依次输出所有这些字母。
【输入格式】
一个只包含大写字母的字符串 S S S。
【输出格式】
若干个大写字母,代表答案。
【样例输入】
BABBACAC
【样例输出】
AB
【评测用例规模与约定】
对于 100 % 100\% 100% 的评测用例, 1 ≤ ∣ S ∣ ≤ 1 0 6 1 ≤ |S | ≤ 10^6 1≤∣S∣≤106。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
public class Main {
public static void main(String[] args) {
new Main().run(); }
int ans, cnt[] = new int[0x7F];
void run() {
try(BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(System.out)) {
String line = in.readLine();
for (int i = line.length(); i > 0;)
ans = Math.max(ans, ++cnt[line.charAt(--i)]);
for (char c = 'A'; c <= 'Z'; ++c)
if (cnt[c] == ans) out.write(c);
} catch (IOException e) {
e.printStackTrace();
}
}
}
签到题,但 Java 组在这里可以先把快读快写实现一下,说不定后面会用到。
试题 D: 最少刷题数
时间限制: 1.0 s 1.0\mathrm s 1.0s 内存限制: 512.0 M B 512.0\mathrm{MB} 512.0MB 本题总分: 10 10 10 分
【问题描述】
小蓝老师教的编程课有 N N N 名学生,编号依次是 1 ⋯ N 1\cdots N 1⋯N。第 i i i 号学生这学期刷题的数量是 A i A_i Ai。
对于每一名学生,请你计算他至少还要再刷多少道题,才能使得全班刷题比他多的学生数不超过刷题比他少的学生数。
【输入格式】
第一行包含一个正整数 N N N。
第二行包含 N N N 个整数 : A 1 , A 2 , A 3 , ⋯ , A N :A_1, A_2, A_3,\cdots, A_N :A1,A2,A3,⋯,AN。
【输出格式】
输出 N N N 个整数,依次表示第 1 ⋯ N 1\cdots N 1⋯N 号学生分别至少还要再刷多少道题。
【样例输入】
5
12 10 15 20 6
【样例输出】
0 3 0 0 7
【评测用例规模与约定】
对于 30 % 30\% 30% 的数据, 1 ≤ N ≤ 1000 , 0 ≤ A i ≤ 1000 1 ≤ N ≤ 1000, 0 ≤ A_i ≤ 1000 1≤N≤1000,0≤Ai≤1000。
对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 100000 , 0 ≤ A i ≤ 100000 1 ≤ N ≤ 100000, 0 ≤ A_i ≤ 100000 1≤N≤100000,0≤Ai≤100000。
求中位数,有两个细节需要注意:
一、中位数必须为序列 A A A 中的某个确定的数。
二、当一个小于中位数的学生刷题量提升时,小于中位数的学生会减少一个,因此要特判一下中位数前后缀和相等的情况。
import java.io.*;
public class Main {
public static void main(String[] args) {
new Main().run(); }
int N = 100000, arg1, arg2;
int[] cnt = new int[N + 1];
void run() {
PrintWriter out = new PrintWriter(System.out);
int n = nextInt();
int[] A = new int[n];
for (int i = 0; i < n; ++i)
++cnt[A[i] = nextInt()];
for (int i = 0; i <= N; ++i)
if (cnt[i] > 0){
if (arg1 >= n - cnt[i] - arg1) {
arg1 = arg1 == n - cnt[i] - arg1 ? i + 1: i;
arg2 = i;
break;
}
arg1 += cnt[i];
}
for (int i = 0; i < n; ++i) {
out.print(A[i] >= arg2 ? 0 : arg1 - A[i]);
out.write(' ');
}
out.flush();
}
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
int nextInt() {
try {
in.nextToken();
} catch (IOException e) {
e.printStackTrace();
}
return (int)in.nval;
}
}
试题 E: 求阶乘
时间限制: 1.0 s 1.0\mathrm s 1.0s 内存限制: 512.0 M B 512.0\mathrm{MB} 512.0MB 本题总分: 15 15 15 分
【问题描述】
满足 N ! N! N! 的末尾恰好有 K K