第十四届蓝桥杯大赛软件赛省赛Java 研究生组A题

题解:特殊日期

问题描述

给定一个日期范围(1900年1月1日至9999年12月31日),统计其中满足"年份的数字之和等于月份数字之和加上日期数字之和"的所有日期数量。

解题思路

  1. 遍历所有日期:从起始日期到结束日期逐日检查
  2. 数字和计算:分别计算年、月、日的各位数字之和
  3. 条件判断:比较年份数字和与月日数字和之和
  4. 闰年处理:正确处理2月份的天数变化
  5. 边界处理:确保日期递增逻辑正确

完整代码实现

public class Main {
    // 平年各月份天数
    static int[] month = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    // 闰年各月份天数(2月有29天)
    static int[] monthRun = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    public static void main(String[] args) {
        // 起始日期:1900年1月1日
        int y = 1900, m = 1, d = 1;
        // 结束日期:9999年12月31日
        int Dy = 9999, Dm = 12, Dd = 31;
        // 当前月份天数数组指针
        int[] tmpmonth;
        // 满足条件的日期计数器
        int count = 0;
        
        // 主循环:逐日检查直到结束日期
        while (!(y == Dy && m == Dm && d == Dd)) {
            // 根据是否闰年选择月份天数数组
            if (isRunyear(y)) {
                tmpmonth = monthRun;
            } else {
                tmpmonth = month;
            }
            // 日期递增
            d++;
            // 处理月份进位
            if (d > tmpmonth[m]) {
                d = 1;
                m++;
                // 处理年份进位
                if (m > 12) {
                    m = 1;
                    y++;
                }
            }
            
            // 检查当前日期是否满足条件
            if (isOK(y, m, d)) {
                count++;
            }
        }
        // 输出最终结果
        System.out.println(count);
    }
    
    static boolean isOK(int y, int m, int d) {
        return getSum(y) == getSum(m) + getSum(d);
    }

    static int getSum(int n) {
        int sum = 0;
        while (n != 0) {
            int g = n % 10;  // 取最后一位数字
            sum += g;
            n /= 10;         // 去掉最后一位
        }
        return sum;
    }

    static boolean isRunyear(int n) {
        // 闰年规则:
        // 1. 能被400整除的是闰年
        // 2. 能被4整除但不能被100整除的是闰年
        return n % 400 == 0 || (n % 100 != 0 && n % 4 == 0);
    }
}

代码解析

1. 数据结构

  • month数组:存储平年各月份天数(2月28天)
  • monthRun数组:存储闰年各月份天数(2月29天)

2. 主函数逻辑

  1. 初始化起始日期和结束日期

  2. 使用while循环逐日检查:

    • 根据年份判断使用平年还是闰年月份天数
    • 日期递增并处理月份和年份进位
    • 检查当前日期是否满足条件

3. 辅助方法

  • isRunyear():实现闰年判断逻辑
  • getSum():计算任意整数的各位数字之和
  • isOK():检查当前日期是否满足题目条件

复杂度分析

  • 时间复杂度:O(N),其中N为日期总数(约8000年×365天≈3百万次循环)
  • 空间复杂度:O(1),仅使用常数级别的额外空间

关键点说明

  1. 日期递增处理:正确处理月末、年末的进位逻辑
  2. 闰年判断:精确实现闰年规则,确保2月天数正确
  3. 数字和计算:通用方法处理年、月、日的数字和计算
  4. 边界条件:包含起始和结束日期的检查

总结

本题通过系统性地遍历所有可能日期,结合基本的数字操作和日期处理逻辑,准确统计了满足条件的日期数量。

答案:70910

### 第十四届蓝桥杯大赛 Java 研究生详情 #### 比概述 第十四届蓝桥杯全国软件和信息技术专业人才大赛旨在推动软件开发技术的发展,培养大学生的创新思维和实践能力。该事面向全国高校在校学生开放,分为多个竞类别和技术方向。 #### 参对象 比主要针对计算机科学及相关专业的研究生群体。参者需具备扎实的编程基础以及解决实际问的能力。 #### 制安排 - **报名阶段**:通常提前几个月启动,在线注册并提交个人信息完成报名流程。 - **初级选拔)**:采用在线答形式,考察选手的基础理论知识与算法设计水平。目难度适中,覆盖广泛的知识点,包括但不限于数据结构、算法分析等[^1]。 ```java // 示例代码展示如何处理数求和问 public class ArraySum { public static int sumRange(int[] array, int L, int R) { int sum = 0; for (int i = L; i <= R && i < array.length; i++) { sum += array[i]; } return sum; } public static void main(String[] args) { int[] A = {1, 2, 3, 4, 5}; System.out.println(sumRange(A, 1, 3)); // 输出9 } } ``` - **决准备**:晋级选手将进入更深入的技术挑战环节,可能涉及复杂的数据结构操作、高级算法应用等内容。 - **总决**:线下举行,邀请各区优秀代表参与终极对决,争夺全国奖项。 #### 奖项设置 根据成绩排名颁发不同等级的荣誉证书及奖品,鼓励更多年轻人投身于科技创新领域。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

EarthOnline玩家

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

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

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

打赏作者

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

抵扣说明:

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

余额充值