HDU6112 2017百度之星 初赛A轮E

题目在这里>_<

题意

今天是2017年8月6日,农历闰六月十五。
小度独自凭栏,望着一轮圆月,发出了“今夕何夕,见此良人”的寂寞感慨。
为了排遣郁结,它决定思考一个数学问题:接下来最近的哪一年里的同一个日子,和今天的星期数一样?比如今天是8月6日,星期日。下一个也是星期日的8月6日发生在2023年。
小贴士:在公历中,能被4整除但不能被100整除,或能被400整除的年份即为闰年。

思路

直接用星期公式就可以了,要注意的是若输入为2月29日,则需要判断某年是否是闰年再代公式。

星期公式

星期公式有两个,一个是蔡勒(Zeller)公式,一个是基姆拉尔森计算公式( Kim larsson calculation formula )。两个公式都需要把某年的1月或2月当作上一年的13月或14月。

蔡勒公式

蔡勒公式用世纪年份月份天计算,可能取模算出来的答案会是负数,所以需要再取模。

int get(int y,int m,int d)
{
    if(m==1||m==2)
        y--,m+=12;
    int c=y/100;
    y%=100;
    return ( ( c/4-2*c+y+y/4+(26*(m-1)/10)+d-1 )%7 + 7)%7;
}

基姆拉尔森计算公式

基姆拉尔森公式不需要再取模。

int get(int y,int m,int d)
{
    if(m==1 || m==2)  
        y--,m+=12;
    return (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7;
}

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <iostream>
#include <map>
#include <set>
//#define test
using namespace std;
const int Nmax=1e6+7;
typedef long long ll;
int get0(int y,int m,int d)
{
    if(m==1||m==2)
        y--,m+=12;
    int c=y/100;
    y%=100;
    return ( ( c/4-2*c+y+y/4+(26*(m-1)/10)+d-1 )%7 + 7)%7;
}
int get(int y,int m,int d)
{
    if(m==1 || m==2)  
        y--,m+=12;
    return (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7;
}
int is(int x)
{
    if(x%4==0 && x%100!=0)
        return 1;
    if(x%400==0)
        return 1;
    return 0;
}
int main()
{
    #ifdef test
    #endif
    //freopen("5.in","r",stdin);
    int t;
    int d,y,m;
    char c;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%c%d%c%d",&y,&c,&m,&c,&d);
        int now=get(y,m,d);
        int flag=0;
        if(m==2 && d==29)
            flag=1;
        for(int i=y+1;i;i++)
        {
            if(flag && !is(i))
                continue;
            int pre=get(i,m,d);
            if(now==pre)
            {
                printf("%d\n",i);
                break;
            }
        }

    }
    return 0;
}