美国节日(求某天是星期几)

发布于:2023-01-21 ⋅ 阅读:(446) ⋅ 点赞:(0)

一、求某天是星期几

  1. 给定一个基准日期,知道基准日期是星期几(a),算的指定日期(y1,m1,d1)与基准日期(y2,m2,d2)间隔的天数(b)
  2. w = (a + b % 7),如果 w > 7,返回 w % 7,得到星期几

求(y,m,d)是星期几
1、先求 w = (a + b % 7)

2、给定基准日期,公元前1年12月31日为星期七,a = 0

3、求间隔天数,b

  1. [1,y - 1] 的整年数 加上 最后一年的部分天数求得间隔天数,b = (y - 1)* 365 + p * 1 + q,p = [1,y - 1]的闰年数,q = (m, d)是y年的第几天
  2. [(y - 1)* 365 ] 可以化简为(y - 1)

如:39 % 7 = 4,4 % 7 = 4,(4 + 5 * 35)% 7 = 4 % 7,(某个数 + 7的倍数)% 7 = 某个数 % 7, [ (y - 1) * 364 + (y - 1) + p + q ] % 7 = [(y - 1) + p + q ],因为 364(y - 1)是7的倍数

  1. 求p,[1,y - 1] 年间的闰年数
  1. 判断闰年的条件:(y % 4 == 0 && y % 100 != 0) || y % 400 == 0
  2. [1, y-1]有(y - 1)/4个数能被 4 整除,有(y - 1) /100个数能被 100 整除,有(y-1)/400个数能被400整除
  3. p = (y - 1)/4 + (y - 1)/100 + (y-1)/400
    在这里插入图片描述
  1. 求q,(m, d) 是 y 年的第多少天
    public static int diff(int y, int m, int d){
        int[] months = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        if((y % 4 == 0 && y % 100 != 0) || y % 400 == 0){
            months[1] = 29;
        }
        
        int n = 0;
        for (int i = 0; i < m - 1; i++) {
            n += months[i];
        }
        n += d;
        
        return n;
    }
  1. 最终的公式为:b = (y - 1) + (y - 1)/4 - (y - 1)/100 + (y - 1)/400 + q

6、w = (7 + [(y - 1) + (y - 1)/4 - (y - 1)/100 + (y - 1)/400 + q] % 7)

5、判断 w 是否为需要 %7

public static int getWeek(int y, int m, int d){
        int q = diff(y, m, d);
        int week = (7 + ((y - 1) + (y - 1)/4 - (y - 1)/100 + (y - 1)/400 + q)% 7);
        return week == 7 ? week : week % 7;
    }

    public static int diff(int y, int m, int d){
        int[] months = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

        int n = 0;
        for (int i = 0; i < m - 1; i++) {
            n += months[i];
        }
        n += d;

        if(m > 2 && ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)){
            n++;
        }

        return n;
    }

二、求美国节日

关于找到某月的第n个星期e,判断这天是几号

  1. 找到每月1号是星期几(w)
  2. 根据规律,1 + [ 7 + (e - w) ] % 7 + (n - 1) * 7,得到这天是几号

1、题目描述

题目链接
在这里插入图片描述

2、代码解决

import java.util.Scanner;
public class Main {
    // 判断某年某月某日 是星期几
    public static int getWeek(int y, int m, int d){
        int q = diff(y, m, d);
        int week = (7 + ((y - 1) + (y - 1)/4 - (y - 1)/100 + (y - 1)/400 + q)% 7);
        return week == 7 ? week : week % 7;
    }

    // 判断某年某月某日与 公元前1年12月31日 的间隔天数
    public static int diff(int y, int m, int d){
        int[] months = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

        int n = 0;
        for (int i = 0; i < m - 1; i++) {
            n += months[i];
        }
        n += d;

        if(m > 2 && ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)){
            n++;
        }

        return n;
    }

    // 判断某月的第n个星期e 是 几号
    // w - 这个月1号是星期几
    // n - 第几个
    // e - 星期几
    public static int getDay(int w, int n, int e){
        return 1 + (7 + (e - w)) % 7 + (n - 1) * 7;
    }
    
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()){
            int y = scanner.nextInt();


            System.out.printf("%d-01-01\n", y);

            int w = getWeek(y, 1, 1);
            int d = getDay(w, 3, 1);
            System.out.printf("%d-01-%02d\n", y, d);

            w = getWeek(y, 2, 1);
            d = getDay(w, 3, 1);
            System.out.printf("%d-02-%02d\n", y, d);

            // 5月的最后一个星期一
            w = getWeek(y, 6, 1);
            d = w == 1 ? 25 : 31 - (w - 2);
            System.out.printf("%d-05-%02d\n", y, d);

            System.out.printf("%d-07-04\n", y);

            w = getWeek(y, 9, 1);
            d = getDay(w, 1, 1);
            System.out.printf("%d-09-%02d\n", y, d);

            w = getWeek(y, 11, 1);
            d = getDay(w, 4, 4);
            System.out.printf("%d-11-%02d\n", y, d);

            System.out.printf("%d-12-25\n", y);

        }
    } 
}

三、求间隔天数

在这里插入图片描述

public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextInt()) {
            int y1 = scanner.nextInt();
            int m1 = scanner.nextInt();
            int d1 = scanner.nextInt();
            int y2 = scanner.nextInt();
            int m2 = scanner.nextInt();
            int d2 = scanner.nextInt();
            System.out.println(intervalDate(y1, m1, d1, y2, m2, d2));
        }
    }

    public static int intervalDate(int y1, int m1, int d1, int y2, int m2, int d2){
        int p1 = gradeDate(y1, m1, d1);
        int p2 = gradeDate(y2, m2, d2);
        int leapYear = leadYearSum(y1, y2 - 1);

        return (y2 - y1) * 365 + leapYear + p2 - p1;
    }

    // 判断某年是否是闰年
    public static boolean isLeapYear(int y){
        return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
    }

    // 判断 [y1, y2] 年间闰年的天数
    public static int leadYearSum(int y1, int y2){
        int sum = 0;
        for (int i = y1; i <= y2; i++) {
            if(isLeapYear(i)){
                sum++;
            }
        }
        return sum;
    }

    // 判断 (y,m,d) 是 y 年的第几天
    public static int gradeDate(int y, int m, int d){
        int[] months = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        int sum = 0;
        for (int i = 1; i <= m - 1; i++) {
            sum += months[i];
        }

        if(m > 2 && isLeapYear(y)){
            sum++;
        }

        sum += d;
        return sum;
    }

四、淘宝网店

1、题目描述
题目链接

在这里插入图片描述

2、丝路与代码

  1. 可以套用间隔天数的公式,将原来的每个月份的天数改成每月利润数{62, 28, 31, 60, 31, 60, 31, 62, 60, 62, 30, 62}
  2. 需要注意的是,求(y1, m1, d1) ---- (y2, m2, d2) 的利润,包括(y1, m1, d1)、(y2, m2, d2),间隔天数的公式并不包括(y1,m1,d1)天,最后需要添加这一天的利润
  3. (y2 - y1)* 579 + [y1, y2-1]间的闰年数 * 1 + p2 - p1 + (y1, m1, d1)天的利润
    (p表示从 [ (y2, 1,1), (y2, m2, d2) ] 间的利润)
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int y1 = scanner.nextInt();
        int m1 = scanner.nextInt();
        int d1 = scanner.nextInt();
        int y2 = scanner.nextInt();
        int m2 = scanner.nextInt();
        int d2 = scanner.nextInt();

        int[] profit = {0, 62, 28, 31, 60, 31, 60, 31, 62, 60, 62, 30, 62};
        int p1 = getPartProfit(y1, m1, d1, profit);
        int p2 = getPartProfit(y2, m2, d2, profit);

        int result = 579*(y2 - y1) + p2 - p1;
        result += leadYearSum(y1, y2 - 1);
        if(isPrimeMonth(m1)){
            result += 2;
        } else {
            result += 1;
        }

        System.out.println(result);

    }
   
    // 得到当年的部分利润
    public static int getPartProfit(int y, int m, int d, int[] profit){
        int p = 0;

        for (int i = 1; i <= m - 1; i++) {
            p += profit[i];
        }

        if(m > 2 && isLeapYear(y)){
            p += 1;
        }

        if(isPrimeMonth(m)){
            p += d * 2;
        } else {
            p += d;
        }
        return p;
    }

    // 判断是否是素数月
    public static boolean isPrimeMonth(int m){
        return m == 2 || m == 3 || m == 5 || m == 7 || m == 11;
    }

    // 判断某年是否是闰年
    public static boolean isLeapYear(int y){
        return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
    }

    // 判断 [y1, y2] 年间闰年的天数
    public static int leadYearSum(int y1, int y2){
        int sum = 0;
        for (int i = y1; i <= y2; i++) {
            if(isLeapYear(i)){
                sum++;
            }
        }
        return sum;
    }

阳光之城,海韵之都

山东日照

在这里插入图片描述

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到