已知公元1年1月1日是星期一,问某年某月某日是星期几?
Input
输入为三个正整数y,m,d,分别代表年、月、日。其中,1≤y≤500000000000, m和d保证合法。
Output
输出星期几,星期一到星期六分别用1到6表示,星期天用7表示。
首先需要明确的一点是,
万年历以400年为一个周期!!也就是说在进行进一步的运算之前,可以
先让year对400取模,从而大大简化计算。
下面先分析一下我的思路:不可能把每一年的总天数加起来再对7求模,这样运算量太大了。
因为一个平年对7取模是1,一个闰年对七取模是2,所以可以一步步的缩小规模,将一个比400小的年数通过counter记录增加的余数,逐步减小到公元1年,然后再求出总天数,这样就好算很多了。
因为这个算法是我当时粗略的想的,感觉大致是对的,但是真正实现起来的时候出现了几个小问题,下面会具体分析一下。
#include
int get_weekday(long long year,int month,int day);
int get_counter(long long year,int month,int day);
int get_days(int month,int day);
int is_leap(long long year);
int main() {
long long year;
int month,day;
int result;
scanf("%lld%d%d",&year,&month,&day);
result=get_weekday(year,month,day);
printf("%d
",result);
return 0;
}
int get_weekday(long long year,int month,int day) {
int counter=0,days=0;
int result;
counter=get_counter(year,month,day);
days=get_days(month,day);
result=(counter+days)%7;
if(!result) {
return 7;
}
return result;
}
int get_counter(long long year,int month,int day) {
int counter=0;
year%=400;
if(is_leap(year)) {
if(month<=2) {
counter--;
}
}
if(!year) {
counter--;
}
for(;year>1;year--) {
if(is_leap(year)) {
counter+=2;
}
else {
counter++;
}
}
return counter%7;
}
int is_leap(long long year) {
int condition1,condition2;
condition1=!(year%4)&&(year%100);
condition2=!(year%400);
if(condition1||condition2) {
return 1;
}
return 0;
}
int get_days(int month,int day) {
int monthdays[12]={0,31,28,31,30,31,30,31,31,30,31,30};
int days=0;
int i=0;
for(i=0;i
- year的数据类型不能是int,设为long long就够了,否则会出现溢出;
- 第一次进行year对400的取模时,考虑会有的年份是400的倍数,取模后会变成公元0年,但实际我们后来计算天数的时候都是按照公元1年1月1日是星期一来进行计算的,我们又知道每往前推一年天数会少一天,所以counter需要自减一;
- 还有一种情况,比如要求1960 2 25是星期几,如果直接将1960%400=360判断为闰年,会让counter增加两天,但是实际上在2.29号之前的天数不会受该年是否为闰年的影响,只有在二月份之后的天数会受影响,因此在进入循环语句之前,先判断月份是否比二大,再继续操作;
- 最后一件小事情就是monthdays中的数组天数总是上一个月的天数,因此第一个元素是0,第十二个元素是第十一月的天数30。
以上均是个人所想,如果有不足或者更简单的做法请一定要在评论里指出哦!