题目不难,主要是细节太多,很容易产生错误,模拟水题,但不容易AC。
首先是题目信息太多了(废话太多),所以不容易发现有用的信息。所以耐心是关键。
分析题目信息,主要有用信息如下:
1)1年1月1日为星期6
2)润年的判定方法如下:
若year<1582,则year%4==0 为润年,否则为平年
若year>=1582,则year%4==0 && year%100!=0 || year%400==0 为润年,否则为平年,注意1700规定为润年。
3)1752年是不寻常的年份,其9月从3号开始到13号结束都没有天数。
只要把上面的信息挖掘出出来,剩下的就是模拟水题了。
思路如下:令输入为sy,sm,ey,em分别表示起始年、起始月、结束年、结束月
要想一个月是good,则有题目定义:该月的第一个工作日为星期1,转化过来就是改月的第一天是星期6、星期天、或者星期一。当然对于1752年9月比较特殊,因为其3号是没有的,故此时判断条件为星期天或者星期一。
同样要想一个月是lucky,则由题目定义:该月的最后一个工作日为星期5,转化过来就是该月的最后一天为星期6、星期天、或者星期5。这里没有特殊情况,因为1752年9月到13号就结束了,故剩余的还多余2天。
首先可以计算出,sy年sm月第一天是星期几,然后判断满足good条件,计算该月最后一天,判断是否满足lucky条件,注意1752年9月特殊情况处理,直至到达ey年em月为止,计数good和lucky月份个数。
另外就是星期的推算公式了:星期1——天用数字1——7表示
若x日期为星期day,而y日期与x日期相隔n天(包含y不包含x),其y星期D为:D=n%7+day
若D!=7,则D%=7 否则 即为D=7
下面是代码:156K+16MS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int sy,sm,ey,em,c; //起始年、起始月、结束年、结束月
int lucky,good; //计数月份
int mon[13]={0,31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //平年每月天数
bool Is_leapyear(int year){ //根据题目判断是否为润年,注意1700特殊处理
if(year<1582){
if(year%4==0)
return true;
return false;
}
else{
if(year%4==0 && year%100!=0 || year%400==0 || year==1700)
return true;
else
return false;
}
}
int cal(int year,int month){ // 推算起始年、起始月的第一天
int day=0;
for(int i=1;i<year;i++){ // 累加起始年之前的所有天数
if(Is_leapyear(i)) //润年
day+=366;
else //平年
day+=365;
}
for(int i=1;i<month;i++) //累加起始月之前的所有天数
if(i==2 && Is_leapyear(year)) //润年二月份特殊处理
day+=(mon[i]+1);
else
day+=mon[i];
if(year>1752 || year==1752 && month>=10) // 若在起始日期在1752年9月份以后,则要减去1752年空缺的11天
day-=11; //至此已经计算起始日期距离1年1月1日的天数
day=day%7+6; //计算起始日期为星期几
if(day!=7)
return day%7;
else
return day;
}
int main(){
scanf("%d",&c);
while(c--){
scanf("%d%d%d%d",&sy,&sm,&ey,&em); //输入起始日期和结束日期
int first=cal(sy,sm),last,year=sy,month=sm; //计算起始日期星期
//printf("%d\n",first);
lucky=good=0; //初始化为0
while(true){ // 循环判断每个月是否属于good or lucky月份
if(year==ey && month>em || year>ey) //若循环结束
break;
if(month==9 && year==1752){ // 若为特殊情况,即为1752年9月份
if(first==7 || first==1) //若该月第一天为星期天或者星期一则为good
good++;
last=18%7+first; //计算last,由于空缺11天,故为(30-11-1)%7+first
}
else{ //普通情况
if(first==7 || first==1 || first==6) //若该月第一天为星期天、星期六、或者星期1则为good
good++;
if(Is_leapyear(year) && month==2) //计算该月最后一天
last=mon[month]%7+first;
else
last=(mon[month]-1)%7+first;
}
if(last!=7) last%=7; //计算最后一天星期
if(last==6 || last==7 || last==5) //若为星期六、星期天、星期一则为lucky月份
lucky++;
first=last%7+1; // 计算下一个月的第一天星期
if(month==12){ //若为最后一个月,则下一个日期要特殊处理
month=1;
year++;
}
else
month++;
}
printf("%d %d\n",lucky,good); //输出
}
return 0;
}