算法提高 日期计算

问题描述
  已知20111111日是星期五,问YYYYMMDD日是星期几?注意考虑闰年的情况。尤其是逢百年不闰,逢400年闰的情况。
输入格式
  输入只有一行
  YYYY MM DD
输出格式
  输出只有一行
  W
数据规模和约定
  1599 <= YYYY <= 2999
  1 <= MM <= 12
  1 <= DD <= 31,且确保测试样例中YYYYMMDD日是一个合理日期
  1 <= W <= 7,分别代表周一到周日
样例输入
2011 11 11
样例输出
5

思路:对照法。

	首先规定一个已经确定过星期几的日期,这里以2017(平年)年11日星期7,为标准。
输入的年份分为两种情况:
	第一种:
	大于规定的年份,则要计算出,规定年份到输入的年份间的所有天数之和,再模上7(规定的是星期7)得到的即是结果
	第二种:
	小于或等于规定年份,计算该年份到规定年份前的所有天数,再计算在输入的年里,month和day共用多少天,用总天数 - 该年的里实际天数,用7模上这个结果

#include<stdio.h>

int isLeapYear(int n) { //判断是否是润年
	if (n%4==0 && n%100!=0 || n%400==0)
		return 1;
	return 0;
}
int md[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31};//全局变量定义,统一定义平年每月月份 
int main() {
	int year,month,day;
	int i,sum=0,td=0;
	while (scanf("%d%d%d",&year,&month,&day)!=EOF) {
		sum=0;
		td=0;
		if (year>=2017) { //输入的年份>=2017年时 
			for (i=2017; i<year; i++) {
				sum+=365;  //计算2017到year年前的所有天数
				if (isLeapYear(i)) //是闰年天数加1
					sum+=1;
			}
			for (i=1; i<month; i++) {
				sum+=md[i];   //计算在输入的这年里,所有月份的天数之和
				if (i==2&&isLeapYear(year))  //判断这年是不是闰年,是则2月份是的天数要加一
					sum+=1;
			}
			sum+=day-1;  //最终准确的天数
			printf("%d\n",sum%7==0? 7:sum%7);
			
		}else if (year<2017) { //输入的年份小于2017
			for (i=year; i<2017; i++) { //计算输入的年份到规定的2017年前的总天数
				sum+=365;
				if (isLeapYear(i))//是闰年加1天
					sum+=1;
			}
			for (i=1; i<month; i++) {
				td+=md[i];   //td为输入年份该年里的所有天数
				if (i==2&&isLeapYear(year)) { //如果是二月,且该年是闰年的话。
					td+=1;   //增加1天
				}
			}
			td+=day-1;
			sum-=td;
			printf("%d\n",7-sum%7);
		
		}
	}
	return 0;
}

分析:

sum+=day-1;  //最终准确的天数

这里是将大于2017年所有的天数进行一次矫正。2017.1.1是星期7,后面每一个7的倍数取%7等于0,而1%7=1的,所以-1矫正即可。

td+=day-1;
sum-=td;

同样,如果输入的年份小于参照的年份,先进行td+=day-1;将其相对2017.1.1矫正。大哥比方,2016.12.31是星期6,sum-=td;通过矫正后,sum=1,所以输出结果通过7-sum%7再次矫正。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小满@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值