ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

swust oj 题解#509 寝室扫地问题(保姆级教学)

2021-11-22 23:31:09  阅读:217  来源: 互联网

标签:oj int 题解 31 30 Month 509 month sum


目录

题目

思路解析

代码实现


题目

思路解析

按照这个题的思路,我们不妨做一个2007年的日历

然后根据题目要求,排出扫地的人

MonTueWedThuFriSatSun
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)1314
15(ALL)161718192021
222324252627

28

293031
11月1234

想必根据表格,已经找出规律了吧,也就是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;
}

 

标签:oj,int,题解,31,30,Month,509,month,sum
来源: https://blog.csdn.net/qq_62102968/article/details/121481475

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有