蓝桥杯历年省赛真题
点击链接免费加入题单
日期问题
java.time
Java 中用于处理日期和时间的主要类位于 java.time
包中。以下是一些常用的类和其功能的简要介绍:
-
LocalDate:表示日期。它提供了获取年、月、日以及日期之间比较的方法。
LocalDate today = LocalDate.now(); // 获取当前日期 int year = today.getYear(); // 获取年份 int month = today.getMonthValue(); // 获取月份 int day = today.getDayOfMonth(); // 获取日期
-
LocalTime:表示时间。它提供了获取时、分、秒以及时间之间比较的方法。
LocalTime time = LocalTime.now(); // 获取当前时间 int hour = time.getHour(); // 获取小时 int minute = time.getMinute(); // 获取分钟 int second = time.getSecond(); // 获取秒钟
-
LocalDateTime:表示日期和时间。它结合了
LocalDate
和LocalTime
的功能。LocalDateTime dateTime = LocalDateTime.now(); // 获取当前日期和时间
-
Instant:表示从 1970 年 1 月 1 日 00:00:00(UTC 时区)开始的时间戳。它可以用于处理时间戳和计算时间间隔。
Instant instant = Instant.now(); // 获取当前时间戳
-
Duration:表示时间间隔。它可以用于计算两个时间点之间的差异。
Duration duration = Duration.between(start, end); // 计算时间间隔
-
Period:表示日期间隔。它可以用于计算两个日期之间的差异。
Period period = Period.between(startDate, endDate); // 计算日期间隔
-
DateTimeFormatter:用于格式化日期和时间。
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 创建格式化器 String formattedDateTime = dateTime.format(formatter); // 格式化日期和时间
这些类提供了丰富的方法和功能,可以满足大多数日期和时间处理的需求。通过这些类,可以方便地进行日期和时间的操作、计算、比较和格式化。
基础循环遍历模板
对于蓝桥杯所有的日期问题遍历,都可以使用的上
public class Main {
public static void main(String[] args) {
// 循环遍历年份
for (int year = 2000; year <= 2022; year++) {
// 循环遍历月份
for (int month = 1; month <= 12; month++) {
// 循环遍历日期
for (int day = 1; day <= 31; day++) {
// 检查是否需要跳过当前月份的日期判断
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
// 如果是31天的月份,则不做额外判断,直接进入下一天
// 当前月份跳出当前循环,继续下一个月份的循环
continue;
} else if (month == 2) { // 对于2月份的日期判断
// 判断是否为闰年
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
// 如果是闰年且日期超过29天,则跳出当前循环,继续下一个月份的循环
if (day > 29) break;
} else {
// 如果不是闰年且日期超过28天,则跳出当前循环,继续下一个月份的循环
if (day > 28) break;
}
} else { // 对于其他月份的日期判断
// 如果日期超过30天,则跳出当前循环,继续下一个月份的循环
if (day > 30) break;
}
}
}
}
}
}
给定日期问过多少天后日期是多少
星系炸弹 (蓝桥杯C/C++2015B组省赛)
- 题目描述
在 X X X 星系的广袤空间中漂浮着许多 X X X 星人造“炸弹”,用来作为宇宙中的路标。每个炸弹都可以设定多少天之后爆炸。
比如:阿尔法炸弹
2015
2015
2015 年
1
1
1 月
1
1
1 日放置,定时为
15
15
15 天,则它在
2015
2015
2015 年
1
1
1 月
16
16
16 日爆炸。
有一个贝塔炸弹,
2014
2014
2014 年
11
11
11 月
9
9
9 日放置,定时为
1000
1000
1000 天,请你计算它爆炸的准确日期。
请填写该日期,格式为 y y y y yyyy yyyy- m m mm mm- d d dd dd 即 4 4 4 位年份 2 2 2 位月份 2 2 2 位日期。比如: 2015 2015 2015- 02 02 02- 19 19 19。
-
题目答案:2017-08-05
-
题目思路
直接模拟日期的计算与进位,我们假设年份用 y e a r year year 表示,月份用 m o n t h month month 表示,日期用 d a y day day 表示
1.月份进位
(1)小月满31天进1月
(2)大月满32天进1月
(3)2月要分平年闰年,闰年满30天进1月,平年满29天进1月
(4)月份进1之后记得将天数 d a y day day 归1
2.年份进位
月份满13进1年,月份 m o n t h month month 归1
- 题目代码
public class Main {
public static void main(String[] args) {
// 定义存储大月和小月的数组
int[] m1 = {0, 1, 3, 5, 7, 8, 10, 12}; // 数组m1存储大月
int[] m2 = {0, 4, 6, 9, 11}; // 数组m2存储小月
// 初始化日期
int year = 2014, month = 11, day = 9;
// 循环加1000天
for (int i = 1; i <= 1000; i++) {
day++;
// 判断是否是大月
for (int j = 1; j <= 7; j++) {
if (month == m1[j] && day == 32) { // 大月满32天进入下个月
month++;
day = 1; // 天数重新回到1号
break;
}
}
// 判断是否是小月
for (int j = 1; j <= 4; j++) {
if (month == m2[j] && day == 31) { // 小月满31天进入下个月
month++;
day = 1;
break;
}
}
// 单独判断2月
if (month == 2) {
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { // 判断是否是闰年
if (day == 30) { // 闰年满30天进入下个月
month++;
day = 1;
}
} else {
if (day == 29) { // 平年满29天进入下个月
month++;
day = 1;
}
}
}
// 满13个月进1年
if (month == 13) {
month = 1; // 月份回到1月重新计数
year++;
}
}
// 输出结果
System.out.println(year + "-" + month + "-" + day);
}
}
日期与日期之间有多少天
第几天(蓝桥杯C/C++2018B组省赛)
- 题目描述
2000 2000 2000 年的 1 1 1 月 1 1 1 日,是那一年的第 1 1 1 天。那么, 2000 2000 2000 年的 5 5 5 月 4 4 4 日,是那一年的第几天?
- 题目答案:125
- 题目思路
如果只是为了应付这道题目计算器或者手算一下都可以,但如果把题目扩展为任意的两个日期之间间隔多少天我们又该如何去做呢。
其实思路也很简单从开始日期一直加1,直到与最终日期相等为止,在上一题的代码基础上略作修改即可
- 代码
public class Main {
public static void main(String[] args) {
// 定义存储大月和小月的数组
int[] m1 = {0, 1, 3, 5, 7, 8, 10, 12}; // 数组m1存储大月
int[] m2 = {0, 4, 6, 9, 11}; // 数组m2存储小月
int num = 1; // 计数器,用于统计经过的天数
int year = 2000, month = 1, day = 1; // 初始日期
int year2 = 2000, month2 = 5, day2 = 4; // 目标日期
while (true) {
num++; // 天数加一
day++; // 当前日期加一
// 判断是否是大月
for (int j = 1; j <= 7; j++) {
if (month == m1[j] && day == 32) { // 大月满32天进入下个月
month++;
day = 1; // 天数重新回到1号
break;
}
}
// 判断是否是小月
for (int j = 1; j <= 4; j++) {
if (month == m2[j] && day == 31) { // 小月满31天进入下个月
month++;
day = 1;
break;
}
}
// 单独判断2月
if (month == 2) {
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { // 判断是否是闰年
if (day == 30) { // 闰年满30天进入下个月
month++;
day = 1;
}
} else {
if (day == 29) { // 平年满29天进入下个月
month++;
day = 1;
}
}
}
// 满13个月进1年
if (month == 13) {
month = 1; // 月份回到1月重新计数
year++;
}
// 到达目标日期后跳出循环
if (year == year2 && month == month2 && day == day2) {
break;
}
}
// 输出结果
System.out.println(num);
}
}
日期与分钟之间的转换
纪念日(蓝桥杯C/C++2020B组省赛第一场)
- 题目描述
2020 2020 2020 年 7 7 7 月 1 1 1 日是×××××成立 99 99 99 周年纪念日。
×××××成立于 1921 1921 1921 年 7 7 7 月 23 23 23 日。
请问从 1921 1921 1921 年 7 7 7 月 23 23 23 日中午 12 12 12 时到 2020 2020 2020 年 7 7 7 月 1 1 1 日中午 12 12 12 时一共包含多少分钟?
- 题目答案:52038720
- 题目思路
我们此时计算的不是天数,但我们知道一天有多少分钟,所以累加的时候换成 1440 1440 1440 分钟即可。
-
代码
public class Main { public static void main(String[] args) { // 定义存储大月和小月的数组 int[] m1 = {0, 1, 3, 5, 7, 8, 10, 12}; // 数组m1存储大月 int[] m2 = {0, 4, 6, 9, 11}; // 数组m2存储小月 int num = 0; // 计数器,用于统计经过的分钟数 int year = 1921, month = 7, day = 23; // 初始日期 int year2 = 2020, month2 = 7, day2 = 1; // 目标日期 while (true) { num += 24 * 60; // 每天有24小时,每小时有60分钟 day++; // 当前日期加一 // 判断是否是大月 for (int j = 1; j <= 7; j++) { if (month == m1[j] && day == 32) { // 大月满32天进入下个月 month++; day = 1; // 天数重新回到1号 break; } } // 判断是否是小月 for (int j = 1; j <= 4; j++) { if (month == m2[j] && day == 31) { // 小月满31天进入下个月 month++; day = 1; break; } } // 单独判断2月 if (month == 2) { if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { // 判断是否是闰年 if (day == 30) { // 闰年满30天进入下个月 month++; day = 1; } } else { if (day == 29) { // 平年满29天进入下个月 month++; day = 1; } } } // 满13个月进1年 if (month == 13) { month = 1; // 月份回到1月重新计数 year++; } // 到达目标日期后跳出循环 if (year == year2 && month == month2 && day == day2) { break; } } // 输出结果 System.out.println(num); } }
星期与周期性问题
星期计算(蓝桥杯Java2022B组省赛)
- 题目描述
已知今天是星期六,请问 2 0 22 20^{22} 2022 天后是星期几?
注意用数字 1 1 1 到 7 7 7 表示星期一到星期日。
- 题目答案:7
- 题目思路
题目难度不大,我们只需要看一下 $20^{22}\ mod\ 7 $ 之后还剩几天,注意取mod即可。
- 代码
public class Main {
public static void main(String[] args) {
int currentDay = 6;
int ans = 1;
for (int i = 1; i <= 22; i++) {
ans = (ans % 7) * 20 % 7;
}
int nextDay = (currentDay + ans - 1) % 7 + 1;
System.out.println(nextDay);
}
}
时间转换
时间显示(蓝桥杯C/C++2021B组省赛)
- 题目思路
只需要利用取余运算即可,我们假设题目输入为 n n n 毫秒
1.首先将 m s ms ms 转化为 s s s, 1 s = 1000 m s 1s = 1000ms 1s=1000ms 所以开始先除以 1000 1000 1000, n = n / 1000 n = n / 1000 n=n/1000。
2.转化成秒之后,先需要对一天有多少秒进行取余,这样剩下的时间肯定不到一天才能进行时间计算,也就是 m o d 86400 mod\ 86400 mod 86400。
3.对一天有多少秒取余后,我们先算还剩下多少小时也就是 n / 3600 n / 3600 n/3600, 然后再 m o d 3600 mod\ 3600 mod 3600 剩下的秒数计算分钟
4.取余后算一下还有多少分钟也就是 n / 60 n / 60 n/60,最后再 m o d 60 mod\ 60 mod 60 输出还剩下多少秒。
- 代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int h, m, s; // 声明小时、分钟、秒数变量
long n; // 声明输入的毫秒数变量
n = scanner.nextLong(); // 读取输入的毫秒数
// 将毫秒数转换为秒数,并保留最后一天的秒数
n = n / 1000 % 86400;
// 求得最后一天的小时
h = (int) (n / 3600);
// 计算剩余的秒数
n = n % 3600;
// 求得最后一天的分钟
m = (int) (n / 60);
// 计算最后一天的秒数
s = (int) (n % 60);
// 格式化输出时间,并且保证输出的小时、分钟、秒数均为两位数,不足时前面补0
System.out.printf("%02d:%02d:%02d", h, m, s);
scanner.close(); // 关闭Scanner流
}
}
回文日期(蓝桥杯C/C++2020B组省赛第二场)
- 题目思路
1.首先要用 for
循环从题目要求的日期开始往后遍历,假设日期为
d
a
t
e
date
date ,把日期先当作数字也就是从
d
a
t
e
+
1
date + 1
date+1 开始往后遍历。
2.然后我们要判断当前日期是否合法,先利用取余与除法分离出 年/月/日
(1) y e a r = d a t e / 10000 year = date/10000 year=date/10000、 m o n t h = d a t e % 10000 / 100 month = date \% 10000 / 100 month=date%10000/100、 d a y = d a t e % 100 day = date \% 100 day=date%100
(2) 月份和天数必须要符号日期格式, 1 ≤ m o n t h ≤ 12 1\leq month \leq 12 1≤month≤12、天数 d a y day day 要根据大小月和 2 2 2 月平闰年判断合法性
- 代码
import java.util.Scanner;
public class Main {
// 定义数组保存每个月的天数
static int[] months = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
// 检查日期是否合法的方法
static boolean check(int date) {
int year = date / 10000; // 从日期中分离出年
int month = date % 10000 / 100; // 从日期中分离出月
int day = date % 100; // 从日期中分离出日
// 月份和日期为0不合法
if (day == 0 || month <= 0 || month > 12)
return false;
// 判断日期是否合法
if (month != 2 && day > months[month])
return false;
// 2月单独判断日期是否合法
if (month == 2) {
// 判断平闰年
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
// 闰年日期不合法
if (day > 29)
return false;
} else {
// 平年日期不合法
if (day > 28)
return false;
}
}
return true;
}
// 判断是否是回文数的方法
static boolean check1(String s) {
int len = s.length();
for (int i = 0, j = len - 1; i < j; i++, j--) {
if (s.charAt(i) != s.charAt(j))
return false;
}
return true;
}
// 判断是否满足ABABBABA型的方法
static boolean check2(String s) {
if (check1(s)) { // 先确定是否是回文数
// 判断是否满足ABABBABA型
if (s.charAt(0) != s.charAt(2) || s.charAt(1) != s.charAt(3) || s.charAt(0) == s.charAt(1))
return false;
return true;
}
return false;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in); // 创建一个 Scanner 对象用于从标准输入读取数据
int date = scanner.nextInt(); // 读取输入的日期
int flag = 0; // 初始化标志位,用于避免重复输出
// 从给定日期的下一天开始搜索
for (int i = date + 1;; i++) {
if (check(i)) { // 判断日期是否合法
String s = Integer.toString(i); // 将数字转换为字符串,方便进行回文判断
if (check1(s) && flag == 0) { // 判断是否为回文数且标志位为0
System.out.println(i); // 输出结果
flag = 1; // 将标志位设为1,避免重复输出
}
if (check2(s)) { // 判断是否满足ABABBABA型
System.out.println(i); // 输出结果
return; // 结束程序
}
}
}
}
}