N-45. 吻合日 --日期问题

日期问题

想看N-45题解的请目录查找
因为懒所以日期问题一题没写过,什么都不会,来补盲

蔡勒公式

蔡勒公式是求解大部分日期问题的基础,用来推断某年某月某日的星期数。
算星期数的基本思路:
1.找出一个已知年月日和星期数的基点
2.求出基点和所求点的相隔天数
3.相隔天数对7取模,加上基点的星期数,再对7取模。
因此可以找一个比较特殊的日期作为基点,
满足:
1.正好是某年的最后一天(方便计算相隔日期)
2.星期日(方便计算星期数)
设所求日期数为(month, day, year);
要求的相隔日期为 基准所在年与所求年年初的天数d1 + 所求年年初到所求日的天数d2
前者只用将相差年份数 * 365 + 闰年年数
闰年:year % 4 == 0 && year % 100 != 0 || year % 100 == 0 && year % 400 == 0
即膜4余0,膜100不为0,或者膜400余0;
d1 = year * 365 + \([\frac{year}{4}] - [\frac{year}{100}] + [\frac{year}{400}]\)
现在需要求d2
d2是由0-12个月和0-31天构成的
先来研究月数:
每个月至少有28天,我们先加上month * 28,再加上每个月余出来的天数。
这里计算的是到所求月数的月初。

month 1 2 3 4 5
3 0/1 3 2 3
month 6 7 8 9 10
2 3 3 2 3
month 11 12
2 3

发现剩余天数成循环关系,存在循环节{3,2,3,2,3}
3-7月
8-12月
每5个月增加13

N-42

题目描述

每一年都会有很多特殊的日子,而有一种特殊的方式叫做“吻合日”。“吻合日”的定义为:如果某日的日期对10取模后的值等于该日的星期值(周日视为7),则称该日为“吻合日”。如2021年3月3日为周三,是“吻合日”。Jaanai想要你帮她求出在一段时间范围内的“吻合日”的数量及每个星期值下“吻合日”的具体数量。

输入格式:

包含m组数据(m不给出),每组数据有两行:

第一行三个数,代表起始年月日;(含)

第二行三个数,代表终止年月日。(不含)

输出格式:

共m行,每行八个整数,第一个整数代表给出的时间范围内“吻合日”的总数,第2-8个整数代表周一至周日分别的“吻合日”数量,整数之间由一个空格分隔。

行末没有多余空格,但是有换行符。

如果没有什么思路就可以像我一样暴力分类讨论:
对于每一天都处理一下:

上图是最长的情况下需要求的段,需要根据具体时间再细分一下:
两年数相等,月数相等
两年数相等,月数相差1
两年数相等,月数相差大于1
两年数相差等于1
两年数相差大于1(即图中所示最完整的情况)

#include <stdio.h>  
#include <string.h>  
int d[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};  
int year1, month1, day1, year2, month2, day2;  
int cnt[8] = {0};  
int ans = 0;  
int isleap (int year) {  
    if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) return 1;  
    return 0;  
}  
int days (int year, int month) {  
    if (isleap(year) && month == 2) return 29;  
    return d[month - 1];  
}  
void query (int year, int month, int day) {  
    if (month == 1 || month == 2) month += 12, year--;  
    int res =(day + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400 + 1) % 7;  
    if (res == 0) res = 7;  
    if (res == day % 10) {  
        cnt[res] ++; ans ++;  
    }  
}  
void solve () {  
    memset(cnt, 0, sizeof cnt);  
    ans = 0;  
    if (year1 == year2 && month1 == month2) {  
        for (int i = day1; i < day2; i++) query(year1, month1, i);  
        printf("%d ", ans);  
    for (int i = 1; i <= 7; i++) {  
        if (i != 7) printf("%d ", cnt[i]);  
        else printf("%d\n", cnt[i]);  
    }  
    }  
    else if (year1 == year2 && month2 > month1 + 1) {  
        for (int i = day1; i <= days(year1, month1); i++) query(year1, month1, i);  
        for (int i = month1 + 1; i < month2; i++) {  
            for (int j = 1; j <= days(year1, i); j++) {  
                query(year1, i, j);  
            }  
        }  
        for (int i = 1; i < day2; i++) query(year2, month2, i);  
        printf("%d ", ans);  
    for (int i = 1; i <= 7; i++) {  
        if (i != 7) printf("%d ", cnt[i]);  
        else printf("%d\n", cnt[i]);  
    }  
    }  
    else if (year1 == year2) {  
            for (int i = day1; i <= days(year1, month1); i++) query(year1, month1, i);  
            for (int i = 1; i < day2; i++) query(year2, month2, i);  
            printf("%d ", ans);  
    for (int i = 1; i <= 7; i++) {  
        if (i != 7) printf("%d ", cnt[i]);  
        else printf("%d\n", cnt[i]);  
    }  
    }  
    else if (year2 == year1 + 1) {  
            for (int i = day1; i <= days(year1, month1); i++) query(year1, month1, i);  
            for (int i = month1 + 1; i <= 12; i++) {  
                for (int j = 1; j <= days(year1, i); j++) {  
                    query(year1, i, j);  
                }  
            }  
            for (int i = 1; i < month2; i++) {  
                for (int j = 1; j <= days(year1, i); j++) {  
                    query(year2, i, j);  
                }  
            }  
        for (int i = 1; i < day2; i++) query(year2, month2, i);  
        printf("%d ", ans);  
    for (int i = 1; i <= 7; i++) {  
        if (i != 7) printf("%d ", cnt[i]);  
        else printf("%d\n", cnt[i]);  
    }  
    }  
    else {  
    for (int i = day1; i <= days(year1, month1); i++) query(year1, month1, i);  
    for (int i = month1 + 1; i <= 12; i++) {  
        for (int j = 1; j <= days(year1, i); j++) {  
            query(year1, i, j);  
        }  
    }  
    for (int i = year1 + 1; i < year2 ; i++) {  
        for (int j = 1; j <= 12; j++) {  
            for (int k = 1; k <= days(i, j); k++) {  
                query(i, j, k);  
            }  
        }  
    }  
    for (int i = 1; i < month2; i++) {  
        for (int j = 1; j <= days(year2, i); j++) {  
            query(year2, i, j);  
        }  
    }  
    for (int i = 1; i < day2; i++) query(year2, month2, i);  
    printf("%d ", ans);  
    for (int i = 1; i <= 7; i++) {  
        if (i != 7) printf("%d ", cnt[i]);  
        else printf("%d\n", cnt[i]);  
    }  
}  
}  
int main () {  
    while(~scanf("%d%d%d%d%d%d", &year1, &month1, &day1, &year2, &month2, &day2)) {  
        solve();  
    }  
    return 0;  
} 

posted @ 2022-05-09 21:40  misasteria  阅读(200)  评论(0编辑  收藏  举报