算法提高 日期计算

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

思路:对照法。

	首先规定一个已经确定过星期几的日期,这里以2017(平年)年1月1日星期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再次矫正。

上一篇:陈皓鑫:3.31黄金周三走势预测,3.31周三白银操作建议


下一篇:3.29黄金原油操作建议,周一操作策略实时解析