时间(日期)在OI中的应用

时间(日期)在OI中的应用

时间在很多领域都有所应用,其中不乏OI(信息竞赛),下面给大家举一些列子以及相应代码,让你更充分地了解时间。

平闰年

公历年份是4的倍数且不是100的倍数,或公历年份是400的倍数位闰年(四年一闰,百年不闰,四百年再闰),闰年二月有29天。

P5711 闰年判断

题目链接

输入一个年份,判断这一年是否是闰年,如果是输出 1 1 1,否则输出 0 0 0

直接按照前面说说规律判断即可。

#include<iostream>
#include<cstdio>
using namespace std;
int main(){
	int y;
    bool p1,p2,p3;
  	cin>>y;
  	p1=y%4==0;
    p2=y%100==0;
    p3=y%400==0;
    cout<<(p3||p1&&!p2);
  	return 0;
}

P5737 闰年展示

题目链接

输入 x , y x,y x,y,输出 [ x , y ] [x,y] [x,y] 区间中闰年个数,并在下一行输出所有闰年年份数字,使用空格隔开。

依次遍历 x x x y y y,每次判断是否为闰年即可。

#include<bits/stdc++.h>
using namespace std;
int x,y,ans[1000],num;
int main(){
    cin>>x>>y;
    for(int i=x;i<=y;i++){
		if(!(i%400)||!(i%4)&&i%100){
			ans[num++]=i;
		}
	}
    cout<<num<<endl;
	for(int i=0;i<num;i++){
		cout<<ans[i]<<" ";
	}
	return 0;
}

P5716 月份天数

题目链接

输入年份和月份,输出这一年的这一月有多少天。需要考虑闰年。

一,三,五,七,八,十,十二月为大月,31天。

四,六,九,十一为小月,30天。

二月平年28天,闰年29天。

直接判断平闰年,输出对应月份天数即可

#include<iostream>
using namespace std;
int main(){
	int y,m;
    cin>>y>>m;
    switch(m){
    case 1: case3: case 5: case 7: case 8: case 10: case 12:
    cout<<31<<endl;break;
    case 4:  case 6: case 9: case 11:
    cout<<30<<endl;break;
    case 2:  if((y%400==0)||(y%4==0)&&!(y%100==0)){
    cout<<29<<endl;
    }else cout<<28<<endl;
    break;
    default: break;
  }
    return 0;
}

日期推算

P5690 [CSP-S2019 江西] 日期

题目链接

给定一个日期,问至少要改动几个数字才能使这个日期存在

#include<bits/stdc++.h>
using namespace std;
int m,d;
int main(){
	scanf("%d-%d",&m,&d);
	if(d>0&&d<=28){//所有月份都满足
		if(m>0&&m<=12){
			cout<<"0";
		}else {
			cout<<"1";//只改变月份的十位
		}
	}else if(d==29||d==30){//大小月皆满足
		if(m==0||m==2||m>12){//改十位
			cout<<"1";
		}else{
			cout<<"0";	
		}
	}else if(d==31){
		if(m==1||m==3||m==5||m==7||m==8||m==10||m==12){//大月满足
			cout<<"0";
		}else if(m==2||m==4||m==6||m==9||m%10==1){//改变个位(最后一种改十位)
			cout<<"1";
		}else if(m%10==4||m%10==6||m%10==9){//改十位和个位
			cout<<"2";
		}else{//只改十位
			cout<<"1";
		}
	}else if(m==0||m>12){ //日期月份都改十位
		cout<<"2";
	}else{//日期改十位
		cout<<"1";
	}
	return 0;	
}

P2010 [NOIP2016 普及组] 回文日期

题目链接

给定起始日期和终止日期,问期间有多少回文日期(不满8位数要补零)

#include<bits/stdc++.h>
using namespace std;
int l,r,ans;
int main(){
	cin>>l>>r;
	int a=l/10000;
	int b=r/10000;//分离出年份
	for(int i=a;i<=b;i++){
		int mon=i/10%10+i%10*10;
		int day=i/1000+i%1000/100*10;//分离出月份日期
		if(mon<=0||mon>12||day<=0||day>31||i*10000+mon*100+day<l||i*10000+mon*100+day>r) continue; //不是真实日期或不满足要求
		if(mon==2){
			if(day>29) continue;//不是真实日期
			if(day==29){
				if(!((i%4==0&&i%100!=0)||i%400==0)){//不是闰年但有29天
					continue;
				}
			}
		}
		if((mon==4||mon==6||mon==9||mon==11)&&day==31) continue;//不是大月但又31天
		ans++;
	}
	cout<<ans;
	return 0;
}

AT_utpc2012_01 2012年12月02日

题目链接

若月份和天数组成的四位数重新排列后可以变成年份,则该日期为好日子,给定一个日期,问其是否为好日子

#include<bits/stdc++.h>
using namespace std;
string s;
int y,m,d;
int vis1[12],vis2[12];
int main(){
	cin>>s;
	y=(s[0]-'0')*1000+(s[1]-'0')*100+(s[2]-'0')*10+(s[3]-'0');//分离年份
	m=(s[5]-'0')*10+(s[6]-'0');//分离月份
	d=(s[8]-'0')*10+(s[9]-'0');//分离天数
	vis1[y%10]++,vis1[y%100/10]++,vis1[y%1000/100]++,vis1[y/1000]++;
	vis2[m/10]++,vis2[m%10]++,vis2[d/10]++,vis2[d%10]++;
	for(int i=0;i<=9;i++){
		if(vis1[i]!=vis2[i]){//若某一数字在年份和月日组成的数中数量不等,则不是好日子
			cout<<"no"<<endl;
			return 0;
		}
	}
	cout<<"yes"<<endl;
	return 0;
} 

ARC015B 真冬日?真夏日?

题目链接

直接判断即可

#include<bits/stdc++.h>
using namespace std;
int n;
int a[10];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		float x,y;
		cin>>x>>y;
		if(x>=35.0) a[1]++;
		else if(x>=30.0) a[2]++;
		else if(x>=25.0) a[3]++;
		if(y>=25.0) a[4]++;
		if(x>=0.0&&y<0.0) a[5]++;
		if(x<0.0) a[6]++;
	}
	cout<<a[1]<<" "<<a[2]<<" "<<a[3]<<" "<<a[4]<<" "<<a[5]<<" "<<a[6]<<endl; 
	return 0;
} 
扩展

冬令时

夏令时

时间差(时区)

P8831 [传智杯 #3 练习赛] 儒略历

题目链接

#include<bits/stdc++.h>
using namespace std;
string s;
int y,m,d,ans;
int mm[15]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int getm(string x){//得到月份
	if(x[0]=='J'){
		if(x[1]=='A') return 1;
		if(x[2]=='N') return 6;
		return 7;
	}
	if(x[0]=='F') return 2;
	if(x[0]=='M'){
		if(x[2]=='R') return 3;
		return 5;
	}
	if(x[0]=='A'){
		if(x[1]=='P') return 4;
		return 8;
	}
	if(x[0]=='S') return 9;
	if(x[0]=='O') return 10;
	if(x[0]=='N') return 11;
	return 12;
}
int gety(string x){//得到年份
	int y=0;
	for(int i=0;i<x.size();i++){
		y=y*10+x[i]-'0';
	}
	return y;
}
int main(){
	cin>>s;
	if(s[1]>='A'&&s[1]<='Z'){
		d=s[0]-'0';
		m=getm(s.substr(1,3));
		y=gety(s.substr(4));
	}else{
		d=(s[0]-'0')*10+s[1]-'0';
		m=getm(s.substr(2,3));
		y=gety(s.substr(5));
	}
    //除今年外全满的年
	for(int i=1;i<y;i++){
		if(i<1582){//儒略历
			if(i%4==0) ans+=366;
			else ans+=365;
		}else{//格里高利历
			if(i%400==0||(i%4==0&&i%100!=0)) ans+=366;
			else ans+=365;
		}
		//闰年判别不同
	}//除了今月外全满的月
	for(int i=1;i<m;i++){
		ans+=mm[i];
	}
	if((y%400==0||(y%4==0&&y%100!=0))&&m>2) ans++;//闰年二月
	ans+=d;//加上日期
	if(y>1582) ans-=10;//格里高利历
	if(y==1582&&m>=10&&d>=15) ans-=10;//格里高利历
	cout<<ans-1<<endl;//减去公元元年一月一日(起始日)
	return 0;
} 
扩展

儒略历

儒略日

格里高利历

UVA10371 Time Zones

题目描述

#include<bits/stdc++.h>
using namespace std;
int n;
float a[10];
float get(string s){
	if(s=="UTC"||s=="GMT"||s=="WET") return 0;
	else if(s=="BST"||s=="IST"||s=="WEST"||s=="CET") return 1;
	else if(s=="CEST"||s=="EET") return 2;
	else if(s=="EEST"||s=="MSK") return 3;
	else if(s=="MSD") return 4;
	else if(s=="AWST") return 8;
	else if(s=="ACST") return 9.5;
	else if(s=="AEST") return 10;
	else if(s=="ACDT") return 10.5;
	else if(s=="AEDT") return 11;
	else if(s=="NDT") return -2.5;
	else if(s=="ADT") return -3;
	else if(s=="NST") return -3.5;
	else if(s=="EDT"||s=="AST") return -4;
	else if(s=="EST"||s=="CDT") return -5;
	else if(s=="CST"||s=="MDT") return -6;
	else if(s=="MST"||s=="PDT") return -7;
	else if(s=="PST"||s=="AKDT") return -8;
	else if(s=="AKST") return -9;
	else return -10;
}
void print(int x,int y){
	if(x==0) x=12;
	cout<<x<<":";
	if(y<10) cout<<0;
	cout<<y<<" ";
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		string a,b,c,d;
		cin>>a;
		if(a[0]=='n'||a[0]=='m') cin>>c>>d;
		else cin>>b>>c>>d;
		int x=0,y;
		float dx=get(c),dy=get(d);//在前面加上两天(2880分钟)以防往前推算时变为负数
		if(a=="noon") x=3600;
		else if(a=="midnight") x=2880;
		else {
			if(b=="a.m."){
				x+=2880;
				
			}else {
				x+=3600;
			}
			if(a.size()==4) x+=(a[0]-'0')*60+(a[2]-'0')*10+a[3]-'0';
				else x+=(((a[0]-'0')*10+(a[1]-'0'))%12)*60+(a[3]-'0')*10+a[4]-'0';
		}
//		cout<<x<<endl;
		
		if(dx==dy){
			if(a[0]=='n'||a[0]=='m') cout<<a<<endl;
			else cout<<a<<" "<<b<<endl;
			continue;
		}
		float cha=abs(dx-dy);//时区相差小时数
		
		if(dx>dy){
			y=x-cha*60;
		}else y=x+cha*60;
//		cout<<y<<endl<<cha<<endl;
		y=y%1440;
		if(y==720){
			cout<<"noon"<<endl;
			continue;
		}
		if(y==0){
			cout<<"midnight"<<endl;
			continue;
		}
		int h=(y/60-1)%12+1,m=y%60;
		print(h,m);
		if(y>720) b="p.m.";//判断上下午
		else b="a.m.";
		cout<<b<<endl;
	}
	return 0;
} 

UVA700 Date Bugs

题目链接

#include<bits/stdc++.h>
using namespace std;
int n,cnt;
struct year{
	int now,st,ed;
}a[30];
bool cmp(year x,year y){
	return (x.ed-x.st)>(y.ed-y.st);
}
int main(){
	cin>>n;
	while(n){
		cnt++;
		for(int i=1;i<=n;i++){
			cin>>a[i].now>>a[i].st>>a[i].ed;
		}
		sort(a+1,a+1+n,cmp);  //转化为等差数列的公差,公差越大枚举次数越少
		int ny=a[1].now,ans=-10;
		while(ny<10000){
			bool f=0;
			for(int i=2;i<=n;i++){
				if(ny<a[i].now){
					f=1;
					break;
				}
				if((ny-a[i].now)%(a[i].ed-a[i].st)!=0){//看是否与其他表示方式冲突(无法获得该日期)
					f=1;
					break;
				}
			}
			if(!f){
				ans=ny;
				break;
			}
			ny+=a[1].ed-a[1].st;
		}
		if(ans!=-10){
			printf("Case #%d:\nThe actual year is %d.\n\n",cnt,ans);
		}else{
			printf("Case #%d:\nUnknown bugs detected.\n\n",cnt);
		}
		//记得换行
		cin>>n;
	}
	
	return 0;	 
}

扩展

B2074 计算星期几 链接
AT_code_festival_qualA_c 2月29日 链接
P8651 [蓝桥杯 2017 省 B] 日期问题 链接
P8748 [蓝桥杯 2021 省 B] 时间显示 链接
AT_arc023_1 [ARC023A] 経過日数 链接
P8547 小挖的时间 链接
P8665 [蓝桥杯 2018 省 A] 航班时间 链接
UVA518 Time 链接
P7267 [BalticOI 2000] Time Zones 链接

一些关于时间的网站

timeanddate.com

timeanddate.com
timeanddate.com
timeanddate.com的主页,可见其覆盖面之广。
在这里插入图片描述

世界时区图,非常详细。

在这里插入图片描述

Codeforces.com 的应用(红框内)。

在这里插入图片描述

AtCoder.jp 的应用(红框内)。

Uoj.ac 也有其应用。

time.is

time.is

在这里插入图片描述

Time.is 的主页,简约风。

在这里插入图片描述
纽约地区的详细内容。

包括该城市所在的国家的一些知名城市,时区,时间差,日出,日落,昼长,太阳时,地图上的位置(海拔,人口,经纬度),年均气温(少数城市有数据)。

结语

时间可以说是最公平的东西之一了。

每个人的时间同时在流逝,不因谁的职业,社会地位,年龄,性别而改变,所以只有掌握分配时间的方法,才能让每一天有尽可能多的进步,从而有更多机遇和选择的权利。

电影《超体》中有一个片段:一辆小车在环形公路上行驶,当无限加速其运动时,它最终却会消失,而时间则是唯一证明它存在过的东西。

愿时间能记录下我们每个人的奋斗与欢喜,证明我们曾经热爱过……

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
后缀自动机被广泛应用OI竞赛,特别是在字符串相关的问题。它是一种高效的数据结构,能够有效地解决各种字符串匹配、模式匹配和计数等问题。 首先,后缀自动机可以用于解决最长公共子串和最长公共子序列等问题。对于给定的两个字符串,可以将其加入到后缀自动机,并通过动态规划的方式求解最长公共子串或子序列的长度。 其次,后缀自动机还可以用于解决多次询问下的子串出现次数问题。通过构建全局后缀自动机,可以在O(n)的时间复杂度内预处理字符串,并在O(m)的时间复杂度内得出任意子串的出现次数,其n为字符串长度,m为询问总数。 另外,后缀自动机还可以用于解决包含多模式匹配的问题。通过将模式串加入到后缀自动机,并预处理自动机的fail指针,可以在O(n)的时间复杂度内找到所有模式串在文本的出现位置。这在处理大规模的文本匹配问题时非常有用。 此外,后缀自动机还可以进行字符串的字典序统计。通过在构建自动机时记录每个节点的信息,可以在O(n)的时间复杂度内得到字符串的字典序第k小/大的子串。 总之,后缀自动机在OI竞赛有着广泛的应用,能够解决各种字符串相关的问题。通过巧妙地构建自动机,并充分利用其性质,可以实现高效的字符串算法,为解决复杂的字符串问题提供了有力的工具。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值