日期类相关题目总结笔记,知识点补充set容器知识点。

2.例题一:Day of Week

题目内容:

We now use the Gregorian style of dating in Russia. The leap years are years with number divisible by 4 but not divisible by 100, or divisible by 400.

For example, years 2004, 2180 and 2400 are leap. Years 2004, 2181 and 2300 are not leap. Your task is to write a program which will compute the day of week corresponding to a given date in the nearest past or in the future using today’s agreement about dating.
input:
There is one single line contains the day number d, month name M and year number y(1000≤y≤3000). The month name is the corresponding English name starting from the capital letter.
output:
Output a single line with the English name of the day of week corresponding to the date, starting from the capital letter. All other letters must be in lower case.
样例输入:

21 December 2012
5 January 2013

样例输出:
Friday
Saturday

#include <cstdio>
#include <string>
#include <iostream>
using namespace std;
string smonth[13] = {
    
    "0","January","February","March","April","May","June"
,"July","August","September","November","December"};
string week[8] = {
    
    "0","Monday","Tuesday","Wednesday","Thursday","Friday"
,"Saturday","Sunday"};
int month[13][2] = {
    
    {
    
    0,0},{
    
    31,31},{
    
    28,29},{
    
    31,31},{
    
    30,30},{
    
    31,31},{
    
    30,30},{
    
    31,31},{
    
    31,31},{
    
    30,30},{
    
    31,31},{
    
    30,30}}; 
int dd,yy,mm;
string smm;

int find_m(string t){
    
    
	for(int i=1;i<=12;i++){
    
    
		if(t==smonth[i]) return i;
	}
}
bool is_leap(int t){
    
    
	return (t%4==0&&t%100!=0)||(t%400==0);
}
int sum_d(int d,int m,int y){
    
    
	int day = 0;
	for(int i=0;i<y;i++){
    
    
		day += is_leap(i)?366:365;
	}
	for(int i=1;i<m;i++){
    
    
		day += month[i][is_leap(y)];
	}
	day += d-1;
	return day;
}

int main(){
    
    
	while(cin>>dd>>smm>>yy){
    
    
		mm = find_m(smm);
		//int t = sum_d(18,5,2020);
		//cout<<t<<endl;    这天为星期一,离公元元年有737634天 
		int amount = sum_d(dd,mm,yy)-737634;
		int res = ((amount%7)+7)%7;  //防止输入中有大于2020-5-18的日期 
		printf("%s\n",week[1+res].c_str());
	}
	return 0;
}

例题2:蓝桥日期问题

题目内容:
问题描述
  小明正在整理一批历史文献。这些历史文献中出现了很多日期。小明知道这些日期都在1960年1月1日至2059年12月31日。令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。

比如02/03/04,可能是2002年03月04日、2004年02月03日或2004年03月02日。

给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?
input:
一个日期,格式是"AA/BB/CC"。 (0 <= A, B, C <= 9)
output:
输出若干个不相同的日期,每个日期一行,格式是"yyyy-MM-dd"。多个日期按从早到晚排列。
样例输入:

02/03/04

样例输出:
2002-03-04
2004-02-03
2004-03-02

PS:
数据规模和约定
  峰值内存消耗(含虚拟机) < 256M
  CPU消耗 < 1000ms
  请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
  注意:
  main函数需要返回0;
  只使用ANSI C/ANSI C++ 标准;
  不要调用依赖于编译环境或操作系统的特殊函数。
  所有依赖的函数必须明确地在源文件中 #include
  不能通过工程设置而省略常用头文件。
  提交程序时,注意选择所期望的语言类型和编译器类型。

#include <cstdio>
#include <set>
#include <string>
using namespace std;
int m_month[13]={
    
    0,31,28,31,30,31,30,31,31,30,31,30,31};
class data {
    
    
	public:
		data(int yy,int mm,int dd) : year(yy),month(mm),day(dd) {
    
     } 
		
		bool operator < (data t) const{
    
    
			if(year==t.year){
    
    
				if(month==t.month){
    
    
					return day<t.day;
				}
				else return month<t.month;
			}
			else return year<t.year;
		}
		
		bool is_legal(){
    
    
			if(year<1960||year>2059) return false;
			else{
    
    
				if(month>0&&month<13){
    
    
					if((year%4==0&&year%100!=0)||year%400==0){
    
    
						if(month == 2){
    
    
							if(day<30&&day>0)  return true;
							else return false;
						}
					}
					if(day<=m_month[month]&&day>0) return true;
					else return false;
				}
				else return false;
			}
		}
		
		void print() const{
    
    
			printf("%d-%02d-%02d\n",year,month,day);//一般日期的输出格式int类型都是这样有些需要在第一个加上%04 
		}
	private:
		int year,month,day;
}; 
set <data> dt;
void insert(int y,int m,int d){
    
    
	data temp(y,m,d);
	if(temp.is_legal()) dt.insert(temp);	
}

int main(){
    
    
	int aa,bb,cc;
	scanf("%d/%d/%d",&aa,&bb,&cc);
	insert(aa+2000,bb,cc);
	insert(aa+1900,bb,cc);
	insert(cc+1900,aa,bb);
	insert(cc+2000,aa,bb);
	insert(cc+1900,bb,aa);
	insert(cc+2000,bb,aa);
	for(set<data>::iterator it=dt.begin();it!=dt.end();++it){
    
    
		it->print();
	}
	return 0;
	
}

set 知识点补充:

1set(集合)

因为是集合所以有着互异性,set里面的各元素是各不相同的,而且set会按照元素进行从小到大排序

2 set的定义

set<int> s; 定义一个空集合s,其中typename 中可以是double,结构体,类,或者是其他容器。
set<double> t[n] ; 则每个t[0]~t[n-1]每一个都是一个set容器。

3 set内元素的访问

只能通过迭代器访问,例如:set <int> :: interator it;

for(set \<int> ::interator it = s.begin();it!= s.end(
;it++){
    
    
		printf("%d",*it)
}

或者,将set <int> ::interator 用auto 表示

4 set常用函数:

4.1 insert()
for (int i = 0; i < 6; i++) {
    
    
s.insert(i); // 向集合s⾥⾯插⼊i
}
4.2. find()
*(s.find(2))  // 如果2存在,则printf 结果为2。
s.find(2)!=s.end() // 判断该元素是否存在
4.3. erase()

s.erase(s.find(1)) // 删除单个元素 ,这个方法空间复杂度为0(1)
s.erase(100) // 删除的单个元素,这个是个为O(logn)
s.erase(s.find(300),s.end()) // 删除元素300到set末尾之间的元素
4. size()
所有容器通用的获得容器大小的函数。
s.size()
5. clear()
s.clear() //清空set 容器,则s.size() = 0;

5 set常见应用:

自动升序排序,去重。

总结

判断闰年函数

if((year%4==0&&year%100!=0)||year%400==0)

bool is_leap(int t){
    
    
	return (t%4==0&&t%100!=0)||(t%400==0);
}

判断每月天数是否合法

int month[13][2] = {
    
    {
    
    0,0},{
    
    31,31},{
    
    28,29},{
    
    31,31},{
    
    30,30},{
    
    31,31},{
    
    30,30},{
    
    31,31},{
    
    31,31},{
    
    30,30},{
    
    31,31},{
    
    30,30}}; 
day <= month[mm][is_leap(yy)]; 

或者

int m_month[13]={
    
    0,31,28,31,30,31,30,31,31,30,31,30,31};
if((year%4==0&&year%100!=0)||year%400==0){
    
    
						if(month == 2){
    
    
							if(day<30&&day>0)  return true;
							else return false;
						}
					}
if(day<=m_month[month]&&day>0) return true;
else return false;

日期的输出

printf("%d-%02d-%02d\n",year,month,day);//一般日期的输出格式int类型都是这样有些需要在第一个加上%04 

一般日期都是花样搞计数,所以写多了些就会慢慢熟练了。这是这段时间写的比较有代表性的两道题。

勉励
打卡第十二天,加油ヾ(◍°∇°◍)ノ゙

如果觉得我的文章对你有所帮助与启发,点赞给我个鼓励吧(づ ̄3 ̄)づ╭❤
关注我和我一起共勉加油吧!
如果文章有错误,还望不吝指教!

猜你喜欢

转载自blog.csdn.net/qq_43992949/article/details/106182984