poj3393

6 篇文章 0 订阅

题目不难,主要是细节太多,很容易产生错误,模拟水题,但不容易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;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值