目录
题目
思路解析
代码实现
按照这个题的思路,我们不妨做一个2007年的日历
然后根据题目要求,排出扫地的人
Mon | Tue | Wed | Thu | Fri | Sat | Sun | |
9月 | 1(B) | 2(X) | |||||
3(ALL) | 4(H) | 5(P) | 6(B) | 7(X) | 8(H) | 9(P) | |
10(ALL) | 11(B) | 12(X) | 13(H) | 14(P) | 15(B) | 16(X) | |
17(ALL) | 18(H) | 19(P) | 20(B) | 21(X) | 22(H) | 23(P) | |
24(ALL) | 25(B) | 26(X) | 27(H) | 28(P) | 29(B) | 30(X) | |
10月 | 1(ALL) | 2(H) | 3(P) | 4(B) | 5(X) | 6(H) | 7(P) |
8(ALL) | 9(B) | 10(X) | 11(H) | 12(P) | 13 | 14 | |
15(ALL) | 16 | 17 | 18 | 19 | 20 | 21 | |
22 | 23 | 24 | 25 | 26 | 27 | 28 | |
29 | 30 | 31 | |||||
11月 | 1 | 2 | 3 | 4 |
想必根据表格,已经找出规律了吧,也就是14天一个轮回。 因此,愉快的开始打表生活
//c++ 代码 string name[14]={"B","X","ALL","H","P","B","X","H","P","ALL","B","X","H","P"};//打表输入人 //c语言代码 char name[][14]={"B","X","ALL","H","P","B","X","H","P","ALL","B","X","H","P"};//打表输入人
由于是14天一个轮回,因此我们可以求出总天数,然后mod14。
然而,每个月的日期又不一样,因此又开始愉快的打表生活
int Month[14]={0,31,28,31,30,31,30,31,31,30,31,30,31,0};//打表输入月份
假设目标日期为2007年10月20日,通过口算是49天,然后我们很容易想出暴力解法。
int year=2007,month=10,day=20; int sum=0; for(int i=9;i<=month;i++){ sum+=Month[i]; } sum+=365*(year-2007); sum+=day-1;
但是如果是2008年呢?2009年呢?(因为i初始为9,如果求的是4月,这样的代码就不行)然后又要去if else特判,这样未免显得有点复杂。
因此我们不妨做一个处理,把每个月份的第一天到年末的天数算出来。
int Month[14]={0,31,28,31,30,31,30,31,31,30,31,30,31,0}; int sum=0,month=10,day=20; //后缀求和,这样Month[i]就表示到年末的天数了 for(int i=12;i>=1;i--){ Month[i]+=Month[i+1]; } //然后与9月1日的天数差就可以这样表示 sum=Month[9]-Month[month]+day-1;
看到这里,想必大家会有点蒙。
由于我们做了后缀和处理,实际上现在的Month[9]==30+31+30+31=122,也就是9月1日到年末12月31日的天数了,由于假设的month=10,所以Month[10]=31+30+31=92,也就是10月1日到年末的天数啦。两式相减就是刚好30天,也就是9月的天数,然后我们再加上day的天数-1(减去9月1日)就是总天数49天啦。
然后大家想必还会觉得我这样多此一举,那不妨我们再举个例,2008年2月10日。
还是通过口算得知为162天
int Month[14]={0,31,28,31,30,31,30,31,31,30,31,30,31,0}; int sum=0,year=2008,month=2,day=10; //后缀求和,这样Month[i]就表示到年末的天数了 for(int i=12;i>=1;i--){ Month[i]+=Month[i+1]; } //然后与9月1日的天数差就可以这样表示 sum=Month[9]-Month[month]+day-1; sum+=365*(year-2007);
由于后缀和处理,现在的Month[2]即为334了,也就是2月1日到12月31日的天数啦。
带入式子计算sum=365+122-334+10-1=162。计算结果完美符合推测。
综上所述,求和代码即:
sum=365*(year-2007)-Month[month]+Month[9]+day-1;
但是呢,别以为这就完了,题目还有个坑,也就是2008年为闰年!!!2月有29天呢。
通过之前的求和,得知2007年9月1日到2008年2月28日刚好是180天。
因此,当sum>180时,我们让sum++。细心的同学已经发现,这样不就没181了吗?
没错,181即为2月29日,因此我们单独列出来就行。
if(sum>180) sum++; if(year==2008&&month==2&&day==29) sum=181;
好了,费了这么久的求和总算求完了,接下来就是输出了。
由于之前的规律,我们清楚14天一个轮回,所以只需sum%14就行,也就是输出name[sum%14]。
最后再将以上散装代码组合即可。
c语言
#include<bits/stdc++.h> int Month[14]={0,31,28,31,30,31,30,31,31,30,31,30,31,0};//打表输入月份 char name[][14]={"B","X","ALL","H","P","B","X","H","P","ALL","B","X","H","P"};//打表输入人 int main() { //输入年月日 int year,month,day,sum; scanf("%d %d %d",&year,&month,&day); //后缀和 for(int i=12;i>=1;i--){ Month[i]+=Month[i+1]; } //计算总天数 sum=365*(year-2007)-Month[month]+Month[9]+day-1; if(sum>180) sum++; if(year==2008&&month==2&&day==29) sum=181; //输出 printf("%s\n",name[sum%14]); return 0; }
C++
#include<bits/stdc++.h> using namespace std; int Month[14]={0,31,28,31,30,31,30,31,31,30,31,30,31,0};//打表输入月份 string name[14]={"B","X","ALL","H","P","B","X","H","P","ALL","B","X","H","P"};//打表输入人 int main() { //输入年月日 int year,month,day,sum; cin>>year>>month>>day; //后缀和 for(int i=12;i>=1;i--){ Month[i]+=Month[i+1]; } //计算总天数 sum=365*(year-2007)-Month[month]+Month[9]+day-1; if(sum>180) sum++; if(year==2008&&month==2&&day==29) sum=181; //输出 cout<<name[sum%14]<<endl; return 0; }