日期问题合集
求解两个日期之间的差值
有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天。
输入格式
输入包含多组测试数据。
每组数据占两行,分别表示两个日期,形式为 YYYYMMDD
。
输出格式
每组数据输出一行,即日期差值。
数据范围
年份范围 $ [1,9999] $,
保证输入日期合法。
输入样例:
20110412
20110422
输出样例:
11
#include <bits/stdc++.h>
using namespace std;
const int N = 13;
int months[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int a,b;
int get(int x)
{
int y = x/10000;
int m = x%10000/100;
int d = x%100;
if (y%4==0&&y%100!=0 || y%400==0) months[2]=29;
else months[2]=28;
while (m--) d+=months[m]; // 本年内的1~m月的天数
while (y--) d+=(y%4==0&&y%100!=0||y%400==0?366:365); // 加上1~y的所有年份的天数
return d;
}
int main()
{
while (cin>>a>>b)
cout<<abs(get(a)-get(b))+1<<endl;
return 0;
}
回文日期问题
在日常生活中,通过年、月、日这三个要素可以表示出一个唯一确定的日期。
牛牛习惯用 $ 8 $ 位数字表示一个日期,其中,前 $ 4 $ 位代表年份,接下来 $ 2 $ 位代表月份,最后 $ 2 $ 位代表日期。
显然:一个日期只有一种表示方法,而两个不同的日期的表示方法不会相同。
牛牛认为,一个日期是回文的,当且仅当表示这个日期的 $ 8 $ 位数字是回文的。
现在,牛牛想知道:在他指定的两个日期之间(包含这两个日期本身),有多少个真实存在的日期是回文的。
一个 $ 8 $ 位数字是回文的,当且仅当对于所有的 $ i \((\) 1≤i≤8 $) 从左向右数的第 $ i $ 个数字和第 $ 9−i $ 个数字(即从右向左数的第 $ i $ 个数字)是相同的。
例如:
- 对于 $ 2016 $ 年 $ 11 $ 月 $ 19 $ 日,用 $ 8 $ 位数字 $ 20161119 $ 表示,它不是回文的。
- 对于 $ 2010 $ 年 $ 1 $ 月 $ 2 $ 日,用 $ 8 $ 位数字 $ 20100102 $ 表示,它是回文的。
- 对于 $ 2010 $ 年 $ 10 $ 月 $ 2 $ 日,用 $ 8 $ 位数字 $ 20101002 $ 表示,它不是回文的。
输入格式
输入包括两行,每行包括一个 $ 8 $ 位数字。
第一行表示牛牛指定的起始日期 $ date_1 $,第二行表示牛牛指定的终止日期 $ date_2 $。保证 $ date_1 $ 和 $ date_2 $ 都是真实存在的日期,且年份部分一定为 $ 4 $ 位数字,且首位数字不为 $ 0 $。
保证 $ date_1 $ 一定不晚于 $ date_2 $。
输出格式
输出共一行,包含一个整数,表示在 $ date_1 $ 和 $ date_2 $ 之间,有多少个日期是回文的。
输入样例:
20110101
20111231
输出样例:
1
日期一共8位,那么我们可以枚举前4位来生成回文日期,然后判断:
- 回文日期是否合法
- 回文日期是否在给定的两个日期范围之内
#include <bits/stdc++.h>
using namespace std;
const int N = 13;
int m[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int a,b;
bool check(int date)
{
int year = date / 10000;
int month = date % 10000 / 100;
int day = date % 100;
if (!month || month >= 13 || !day) return false;
if (month != 2 && day > m[month]) return false;
if (month == 2)
{
bool leap = year % 4 == 0 && year % 100 || year % 400 == 0;
if (day > 28 + leap) return false;
}
return true;
}
int main()
{
cin>>a>>b;
int ans = 0;
for (int i=1;i<100000;i++)
{
int x=i,y=i;
for (int j=0;j<4;j++) x = x*10+y%10,y/=10;
if (check(x)&&x>=a&&x<=b) ans++;
}
cout<<ans<<endl;
return 0;
}
已知年份和天数,求是这年的几月几日
给定一个年份 $ y $ 和一个整数 $ d $,问这一年的第 $ d $ 天是几月几日?
注意闰年的 $ 2 $ 月有 $ 29 $ 天。
满足下面条件之一的是闰年:
- 年份是 $ 4 $ 的整数倍,而且不是 $ 100 $ 的整数倍;
- 年份是 $ 400 $ 的整数倍。
输入格式
输入的第一行包含一个整数 $ y $,表示年份,年份在 $ 1900 $ 到 $ 2015 $ 之间(包含 $ 1900 $ 和 $ 2015 $)。
输入的第二行包含一个整数 $ d \(,\) d $ 在 $ 1 $ 至 $ 365 $ 之间。
输出格式
输出两行,每行一个整数,分别表示答案的月份和日期。
数据范围
$ 1900 \le y \le 2015 \(, \) 1 \le d \le 365 $
输入样例1:
2015
80
输出样例1:
3
21
输入样例2:
2000
40
输出样例2:
2
9
思路
就是从一月开始枚举,如果剩余天数能减去整月就减,减不了就确定了月份和天数的答案了。还是要注意一下二月和闰年的特判。
#include <bits/stdc++.h>
using namespace std;
const int N = 13;
int m[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int a,b;
int main()
{
cin>>a>>b;
if (a%4==0&&a%100!=0||a%400==0) m[2]=29;
else m[2]=28;
int month=0,day=0;
for (int i=1;i<13;i++)
{
if (b>m[i]) // 够整月减
{
b-=m[i];
month++;
}
else // 不够整月减
{
month++;
day = b;
break;
}
}
cout<<month<<endl<<day<<endl;
return 0;
}
给出一个日期,输出下一天的日期
编写一个日期类,要求按 xxxx-xx-xx
的格式输出日期,实现加一天的操作。
输入格式
第一行包含整数 $ T $,表示共有 $ T $ 组测试数据。
每组数据占一行,包含 $ 3 $ 个用空格隔开的整数,分别表示年月日。
输出格式
每组数据输出一行,一个结果,按 xxxx-xx-xx
的格式输出,表示输入日期的后一天的日期。
数据范围
输入日期保证合法且不会出现闰年。
年份范围 $ [1000,3000] $
输入样例:
2
1999 10 20
2001 1 31
输出样例:
1999-10-21
2001-02-01
只需要特判一下:
- 本年的最后一天
- 本月的最后一天
- 正常日期
#include <bits/stdc++.h>
using namespace std;
const int N = 13;
int m[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int n;
int main()
{
cin>>n;
while (n--)
{
int a,b,c;
cin>>a>>b>>c;
// 特判本年的最后一天
if (b!=12&&c==m[b]) printf("%d-%02d-%02d\n",a,b+1,1);
// 特判本月的最后一天
else if (b==12&&c==m[b]) printf("%d-%02d-%02d\n",a+1,1,1);
// 正常的日期
else printf("%d-%02d-%02d\n",a,b,c+1);
}
return 0;
}
给出年份 $ y $ 和一年中的第 $ d $ 天,算出第 $ d $ 天是几月几号。
给出年份 $ y $ 和一年中的第 $ d $ 天,算出第 $ d $ 天是几月几号。
输入格式
输入包含多组测试数据。
每组数据占一行,包含两个整数 $ y $ 和 $ d $。
输出格式
每组数据输出一行一个结果,格式为 yyyy-mm-dd
。
数据范围
输入最多包含 $ 100 $ 组数据,
$ 1 \le y \le 3000 \(,
\) 1 \le d \le 366 $,
数据保证合法。
输入样例:
2000 3
2000 31
2000 40
2000 60
2000 61
2001 60
输出样例:
2000-01-03
2000-01-31
2000-02-09
2000-02-29
2000-03-01
2001-03-01
和给出年份与天数,确定几月几日是一模一样的题目。就是直接模拟即可。如果剩余天数大于当前月的天数,更新月份和剩余天数;如果剩余天数不足当前月的天数,更新月份,确定月份和当前月的几号,相当于确定了答案,退出。
#include <bits/stdc++.h>
using namespace std;
const int N = 13;
int m[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int a,b;
int main()
{
while (cin>>a>>b)
{
if (a%4==0&&a%100!=0||a%400==0) m[2]=29;
else m[2]=28;
int year=a,month=0,d=0;
for (int i=1;i<13;i++)
{
if (b>m[i])
{
month++;
b-=m[i];
}
else
{
month++;
d=b;
break;
}
}
printf("%04d-%02d-%02d\n",year,month,d);
}
return 0;
}
从当前日期开始,到指定日期,确定是星期几
今天是 $ 2012 $ 年 $ 4 $ 月 $ 12 $ 日星期四,编写程序,输入今天开始到 $ 12 $ 月 $ 31 $ 日之间的任意日期,输出那一天是星期几。
输入格式
共两行,第一行包含一个整数 $ m $,表示询问日期的月份。
第二行包含一个整数 $ d $,表示询问日期的为该月的第几天。
输出格式
输出询问日期是星期几。
注意,要用英文表示。
周一到周日的英文表示如下:
"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"
数据范围
$ 4 \le m \le 12 \(,
\) 1 \le d \le 31 $,
保证日期合法。
输入样例:
5
20
输出样例:
Sunday
其实这道题的本质就是求解这两个日期之间的天数是多少。确定好之后,天数Mod7,即可确定是星期几。但这里有个细节需要处理一下:当前开始的日期是星期四,因此week数组中的顺序应该是4567123
#include<bits/stdc++.h>
using namespace std;
int a[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
// 因为这天是星期四开始的,因此星期的第一个位置应该是星期四
string week[7]={"Thursday","Friday","Saturday","Sunday","Monday","Tuesday","Wednesday",};
int main()
{
int n,m,day1=0,day2=0;
cin>>n>>m;
for(int i=1;i<4;i++)day1+=a[i];
day1+=12;
for(int i=1;i<n;i++)day2+=a[i];
day2+=m;
// 两个日期之间的天数即可确定
cout<<week[(day2-day1)%7]<<endl;
return 0;
}
3391. 今年的第几天? - AcWing题库
输入年、月、日,计算该天是本年的第几天。
注意闰年的 $ 2 $ 月有 $ 29 $ 天。
满足下面条件之一的是闰年:
- 年份是 $ 4 $ 的整数倍,而且不是 $ 100 $ 的整数倍;
- 年份是 $ 400 $ 的整数倍。
输入格式
输入包含多组测试数据。
每组数据占一行,包含三个整数 $ Y,M,D $,表示年、月、日。
输出格式
每组数据输出一个整数,占一行,表示输入给定的年、月、日对应本年的第几天。
数据范围
$ 1 \le Y \le 3000 \(,
\) 1 \le M \le 12 \(,
\) 1 \le D \le 31 $,
输入最多包含 $ 100 $ 组测试数据。
保证所有日期都是合法的。
输入样例:
1990 9 20
2000 5 1
输出样例:
263
122
没啥好说的,从1~m-1月先枚举求得整月份的天数,再单独加上最后的零散天数即可.
属于是典型的已知年月日,求解时本年度的第几天。
当然,如果本题扩展到不仅限于本年份了,即可能从1999年1月1日开始到当前年月日经过了多少天类似这种要求,那么就变成了求解两个具体日期相隔多少天的问题了。那么就是像之前类似的题目求解方法一样,从1年1月1日开始计算(即从头)到第一个日期求解天数day1,同理求解从头到第二个日期的天数day2,相减作差即可得到答案。
#include <bits/stdc++.h>
using namespace std;
const int N = 13;
int months[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int main()
{
int y,m,d;
while (cin>>y>>m>>d)
{
if (y%4==0&&y%100!=0||y%400==0) months[2]=29;
else months[2]=28;
int ans = 0;
for (int i=1;i<m;i++)
ans+=months[i];
ans+=d;
cout<<ans<<endl;
}
return 0;
}
3489. 星期几 - AcWing题库
已知 $ 1 $ 年 $ 1 $ 月 $ 1 $ 日是星期一。
现在给定一个日期,请你判断是星期几。
注意闰年的 $ 2 $ 月有 $ 29 $ 天。
满足下面条件之一的是闰年:
- 年份是 $ 4 $ 的整数倍,而且不是 $ 100 $ 的整数倍;
- 年份是 $ 400 $ 的整数倍。
输入格式
输入包含多组测试数据。
每组数据占一行,包含一个整数 $ d $ 表示日,一个字符串 $ m $ 表示月,一个整数 $ y $ 表示年。
月份 $ 1 \sim 12 $,依次如下所示:
January, February, March, April, May, June, July, August, September, October, November, December
输出格式
每组数据输出一行结果,输出一个字符串表示给定日期是星期几。
周一至周日依次如下所示:
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
数据范围
$ 1000 \le y \le 3000 $,
给定日期保证合法。
每个输入最多包含 $ 100 $ 组数据。
输入样例:
9 October 2001
14 October 2001
输出样例:
Tuesday
Sunday
这个题本质还是已知具体的日期,求从元年1月1日(包含)到现在经过的天数,然后根据初始的时间节点是星期几,确定当前日期是星期几的问题。注意月份数字与字符串哈希表的写法、月份和月份天数的数组打表写法、星期的打表写法等细节。
#include <bits/stdc++.h>
using namespace std;
const int N = 13;
int month[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
string week[]={"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
unordered_map<string,int>S={
{"January",1},
{"February",2},
{"March",3},
{"April",4},
{"May",5},
{"June",6},
{"July",7},
{"August",8},
{"September",9},
{"October",10},
{"November",11},
{"December",12}
};
int main()
{
int d,y;
string s;
while (cin>>d>>s>>y)
{
int m = S[s];
if (y%4==0&&y%100!=0||y%400==0) month[2]=29;
else month[2]=28;
int ans = 0;
for (int i=1;i<y;i++)
ans+=(i%4==0&&i%100!=0||i%400==0 ? 366:365);
for (int i=1;i<m;i++)
ans+=month[i];
ans+=d;
// 注意:星期的对应是0~6对应星期一到天,去掉第一天的情况
cout<<week[(ans%7-1+7)%7]<<endl;
}
return 0;
}
1341. 十三号星期五 - AcWing题库
十三号星期五真的很不常见吗?
每个月的十三号是星期五的频率是否比一周中的其他几天低?
请编写一个程序,计算 $ N $ 年内每个月的 $ 13 $ 号是星期日,星期一,星期二,星期三,星期四,星期五和星期六的频率。
测试的时间段将会开始于 $ 1900 $ 年 $ 1 $ 月 $ 1 $ 日,结束于 $ 1900+N-1 $ 年 $ 12 $ 月 $ 31 $日。
一些有助于你解题的额外信息:
- $ 1900 $ 年 $ 1 $ 月 $ 1 $ 日是星期一。
- 在一年中,$ 4 $ 月、$ 6 $ 月、$ 9 $ 月、$ 11 $ 月每个月 $ 30 $ 天,$ 2 $ 月平年 $ 28 $ 天,闰年 $ 29 $ 天,其他月份每个月31天。
- 公历年份是 $ 4 $ 的倍数且不是 $ 100 $ 的倍数的年份为闰年,例如 $ 1992 $ 年是闰年,$ 1990 $ 年不是闰年。
- 公历年份是整百数并且是 $ 400 $ 的倍数的也是闰年,例如1700年,1800年,1900年,2100年不是闰年,2000年是闰年。
输入格式
共一行,包含一个整数 $ N $。
输出格式
共一行,包含七个整数,整数之间用一个空格隔开,依次表示星期六,星期日,星期一,星期二,星期三,星期四,星期五在十三号出现的次数。
数据范围
$ 1 \le N \le 400 $
输入样例:
20
输出样例:
36 33 34 33 35 35 34
抽象日期模型还是:已知初始状态的日期年月日,求一个新的日期是星期几。
那么我们的思路还是求解这个新的日期与起点的天数,去取模7计算星期几。
#include <bits/stdc++.h>
using namespace std;
const int N = 13;
int cnt[10];
int month[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int n,w,x;
int main()
{
cin>>n;
int days = 0;
for (int y=1900;y<=1900+n-1;y++)
{
if (y%4==0&&y%100!=0||y%400==0) month[2]=29;
else month[2]=28;
for (int i=1;i<=12;i++)
{
cnt[(days+13-1+7)%7]++;
days+=month[i];
}
}
for (int i=5,j=0;j<7;i=(i+1)%7,j++)
cout<<cnt[i]<<" ";
puts("");
return 0;
}
3573. 日期累加 - AcWing题库
设计一个程序能计算一个日期加上若干天后是什么日期。
输入格式
第一行包含整数 $ T $,表示共有 $ T $ 组测试数据。
每组数据占一行,包含四个整数 $ y,m,d,a $,分别表示给定日期的年、月、日和累加的天数。
输出格式
每组数据输出一行,一个结果,每行按 yyyy-mm-dd
的格式输出。
数据范围
$ 1 \le T \le 1000 $
$ 1000 \le y \le 3000 \(,
\) 1 \le m \le 12 \(,
\) 1 \le d \le 31 \(,
\) 1 \le a \le 10^6 $,
保证输入日期合法。
输入样例:
1
2008 2 3 100
输出样例:
2008-05-13
抽象这道题,就是已知当前日期,求若干天后的日期。一种比较容易想到的写法就是不断让天数--,直到走到那一天。但会TLE
#include <bits/stdc++.h>
using namespace std;
const int N = 13;
int month[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool check(int y)
{
if (y%4==0&&y%100!=0||y%400==0) return true;
return false;
}
int T,y,m,d,a;
int main()
{
scanf("%d",&T);
while (T--)
{
scanf("%d%d%d%d",&y,&m,&d,&a);
while (a--)
{
d++;
if (check(y)) month[2]=29;
else month[2]=28;
if (d>month[m])
{
m++;
d=1;
}
if (m>12)
{
y++;
m=1;
}
}
printf("%02d-%02d-%02d\n",y,m,d);
}
return 0;
}
另一种写法就是先把总天数算出,然后从m这个月开始枚举,边枚举边更新剩余天数等信息。
//按月进行累加进位,最后剩下的就是号
#include <bits/stdc++.h>
using namespace std;
int ms[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool isleap(int y) {
return y%4 == 0 && y%100 != 0 || y%400 == 0;
}
int get(int y, int m) {
if (m != 2) return ms[m];
return 28 + isleap(y);
}
int main() {
int n, y, m, d, a, day;
scanf("%d", &n);
while (n--) {
scanf("%d%d%d%d", &y, &m, &d, &a);
a += d; //日累加到加的总天数上
while (a > get(y, m)) { //加的天数大于该月天数,该月就可以完整过到下一个月
a -= get(y, m);
m++;
if (m > 12) m = 1, y++;
}
printf("%04d-%02d-%02d\n", y, m, a);
}
return 0;
}
AcWing 3498. 日期差值 - AcWing
有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天。
输入格式
输入包含多组测试数据。
每组数据占两行,分别表示两个日期,形式为 YYYYMMDD
。
输出格式
每组数据输出一行,即日期差值。
数据范围
年份范围 $ [1,9999] $,
保证输入日期合法。
输入样例:
20110412
20110422
输出样例:
11
典型的求两个具体日期之间的差值的问题。思路就是分别求出两个日期距离1年1月1日经过的天数,然后相减+1即可。
#include<bits/stdc++.h>
using namespace std;
//存储每月的天数求出来
int a[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//从a[1]开始存
//差分思想
int days(int x)//days函数用于计算到0000/00/00的天数
{
int n = x / 10000;//年
int y = x % 10000 / 100;//月
int r = x % 10000 % 100;//日
//首先更新一下计算年份的二月天数有多少
//闰年包括普通闰年和世纪闰年
//普通闰年年分是4倍数不是100倍数(),世纪闰年是400的倍数,
//即100的倍数不是4的倍数不是闰年,如1900
//判断闰年
if(n % 4 == 0 && n % 100 != 0||n % 400 == 0)
a[2]=29;
else //不加这个会错
a[2]=28;
// a[2] = ( n % 4 == 0 && n % 100 != 0 || n % 400 == 0 ? 29 : 28);//等价写法
//统计当前年份的总天数
while(y --) r += a[y];//把每个月的天数相加,注意初值为把未满一月的天数
//计算从公元1年开始开始,一直到去年最后一天,不是到0000年
while(n --) r += (n % 4 == 0 && n % 100 != 0||n % 400 == 0 ? 366 : 365);//闰年366天,平年365天
return r;//返回一共的天数
}
int main()
{
int a,b;
while(cin >> a >> b)
cout<< abs( days(a) - days(b) )+1 << endl;
//注意需要加一,相邻的两天日期相差1,天数相差2
}
标签:le,int,天数,31,30,问题,日期,合集 From: https://www.cnblogs.com/sdnu-dfl/p/17294360.html