题目描述
有一类节日的日期并不是固定的,而是以$“a 月的第 b 个星期 c”$的形式定下来的,比如说母亲节就定为每年的五月的第二个星期日。
现在,给你 $a,b,c$ 和 $y1,y2$,希望你输出从公元 y1 年到公元 y2 年间的每年的 a 月的第 b 个星期 c 的日期。
提示:关于闰年的规则:年份是 400 的整数倍时是闰年,否则年份是 4 的倍数并且不是 100 的倍数时是闰年,其他年份都不是闰年。
例如 1900 年就不是闰年,而 2000 年是闰年。
为了方便你推算,已知 1850 年 1 月 1 日是星期二。
输入格式
输入包含恰好一行,有五个整数 a,b,c,y1,y2。
其中 $c=1,2,……,6,7$ 分别表示星期一、二、……、六、日。
输出格式
对于 y1 和 y2 之间的每一个年份,包括 y1 和 y2,按照年份从小到大的顺序输出一行。
如果该年的 a 月第 b 个星期 c 确实存在,则以 yyyy/mm/dd
的格式输出,即输出四位数的年份,两位数的月份,两位数的日期,中间用斜杠 /
分隔,位数不足时前补零。
如果该年的 a 月第 b 个星期 c 并不存在,则输出 none
。
数据范围
$1≤a≤12$
$1≤b≤5$
$1≤c≤7$
$1850≤y1,y2≤2050$
输入样例:
5 2 7 2014 2015
输出样例:
2014/05/11
2015/05/10
思路
给大家提供一种“套路”的思路
每个月的天数不一样,我们先把每个月的天数存下来(2月存的是平年的情况),每个月的天数最好对应着下标,方便计算
写一个判断闰年的函数,是闰年就返回1,不是就返回0
写一个函数来求某月有多少天,知识2月需要特判,如果是闰年的话,就天数加1,否则就直接返回数组里的天数即可
星期的话,可以不用对着,因为涉及到取余,7%7=0
所以编号就可以从0开始,更方便一些
以上就是遇到这种日期的题需要做的准备工作
然后我们就开始枚举
年份的话我们从1850年开始枚举,因为题目中给出了“1850年1月1日是星期二”,一直枚举到y2
每一年内的月份从1到12枚举
我们其实就是在算每年每月的1日是距离1850年1月1日过了多少天
然后这个数值加上星期二的下标mod 7就是当前月份1日的星期下标
与此同时我们要记录一下现在枚举到了第几个星期c
然后我们一天一天地枚举,直到枚举到第b个星期c,当然,每过完一天我们的星期也要随之变换
在枚举完这个月之后我们要看一下枚举到了第几个星期c,如果小于b就输出none
代码
#include<iostream>
using namespace std;
int months[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int is_leap(int y)
{
if(y%4==0&&y%100||y%400==0)
return 1;
return 0;
}
int get_days(int y,int m)
{
if(m==2) return months[m]+is_leap(y);
return months[m];
}
int main()
{
int a,b,c,y1,y2;
cin>>a>>b>>c>>y1>>y2;
int day=0,cnt=0,w;
for(int y=1850;y<=y2;y++)
{
for(int m=1;m<=12;m++)
{
if(m==a&&y>=y1)
{
w=(1+day)%7,cnt=0;
for(int d=1;d<=get_days(y,m);d++)
{
if(w==c-1)
{
cnt++;
if(cnt==b)
{
printf("%04d/%02d/%02d\n",y,m,d);
break;
}
}
w=(w+1)%7;
}
if(cnt<b)
cout<<"none"<<endl;
}
day+=get_days(y,m);
}
}
return 0;
}