題目
小藍每天都鍛煉身體。
正常情況下,小藍每天跑 1 千米。如果某天是周一或者月初(1 日),為了激勵自己,小藍要跑 2 千米。如果同時是周一或月初,小藍也是跑 2 千米。小藍跑步已經堅持了很長時間,從 2000 年 1 月 1 日周六(含)到 2020 年10 月 1 日周四(含)。請問這段時間小藍總共跑步多少千米?
思路
我們首先寫一個判斷日期是否合法的函數
check
,這個函數用來檢查一個八位的日期是否合法。
模闆如下
int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
bool check(int date)
{
int year = date / 10000; //年
int month = date % 10000 / 100; //月
int day = date % 100; //日
if(!month || month > 12 || !day ) return false;//如果月份大于12或者為零或者天數為零則該日期不合法
if(month != 2 && day > months[month]) return false;//在不是二月的情況下,該月實際天數大于該月最大天數,則該日期不合法
if(month == 2) //特判二月
{
if((year % 4 == 0&& year % 100 != 0) || (year % 400 == 0))//特判閏年
{
if(day > 29) return false;
}
else if( day > 28) return false;
}
return true;
}
這個模闆要牢記,幾乎可以套所有的日期模拟題,尤其對這種填空題,可以說是大殺器。
然後我們枚舉日期
20000101
到日期
20201001
,篩選出合法的日期。這裡有一個難點,如何判斷某一天是星期幾?其實我們可以發現星期幾是和這天是幾号無關的,因為一周七天,每七天一輪回,該天是星期幾取決于起始日期是星期幾和該天離起始日期多少天。假設終點日期離起始日期
sum
天,起始日期是星期六,我們隻需
(sum + 6) % 7 == 1
就可以輕松判斷出這天是不是星期一。
(sum + 6) % 7 == 0
代表星期日,其餘一 一對應。我們帶一個特殊日期驗證一下,假設終點日期是起始日期,
sum==0
,
(0 + 6) % 7 == 6
,驗證無誤,當然如果不放心的話可以多帶幾個日期驗證一下。
答案: 8879
代碼
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int months[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
bool check(int date)
{
int year = date / 10000;
int month = date % 10000 / 100;
int day = date % 100;
if(!month || month > 12 || !day ) return false;//
if(month != 2 && day > months[month]) return false;
if(month == 2)
{
if((year % 4 == 0&& year % 100 != 0) || (year % 400 == 0))
{
if(day > 29) return false;
}
else if( day > 28) return false;
}
return true;
}
int main()
{
int res = 0,sum = 0;//sum記錄相隔天數,res記錄答案
for(int i = 20000101; i <= 20201001; i++) // 1 2 3
{
if(check(i))
{
res ++ ;
int month = i % 10000 / 100;
int day = i % 100;
if( day == 1 || (sum + 6) % 7 == 1 ) res++; //周一或月初,加一千米
sum ++ ;
}
}
cout<<res<<endl;
return 0;
}