• 日期问题总结


    做日期问题,首先把模版写下来,再根据具体情况具体分析,基本上考试考到日期问题都是模拟和枚举,数据量也不会太大,所以我们根据题目要求直接打暴力就可以过.

    模板:

    1. const int months[]={//平年天数
    2. 0,31,28,31,30,31,30,31,31,30,31,30,31
    3. };
    4. int is_leap(int y){//判断是否为闰年
    5. if(y%100!=0&&y%4==0||y%400==0) return 1;
    6. return 0;
    7. }
    8. int get_month_days(int y,int m){//判断某个月天数
    9. int res=months[m];
    10. if(m==2) res+=is_leap(y);
    11. return res;
    12. }
    13. int get_total_days(int y,int m,int d){//计算第一天到某个日期天数
    14. int res=0;
    15. for(int i=1;i//计算前y-1年的天数
    16. res+=365+is_leap(i);
    17. for(int i=1;i//计算第i年前m-1个月的天数
    18. res+=get_month_days(y,i);
    19. return res+d;//第y年第m月的天数
    20. }

    注 :写日期问题时,这三个模板可能不会都用上,也可能都不会用上.

    例题:

    日期差值

    有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天。

    输入格式

    输入包含多组测试数据

    每组数据占两行,分别表示两个日期,形式为 YYYYMMDD

    输出格式

    每组数据输出一行,即日期差值。

    数据范围

    年份范围 [1,9999]
    保证输入日期合法。
    测试数据的组数不超过 100。

    输入样例:
    1. 20110412
    2. 20110422
    输出样例:
    11
    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. const int N=5e5+5;
    12. typedef long long LL;
    13. using namespace std;
    14. const int months[]={//平年天数
    15. 0,31,28,31,30,31,30,31,31,30,31,30,31
    16. };
    17. int is_leap(int y){//判断是否为闰年
    18. if(y%100!=0&&y%4==0||y%400==0) return 1;
    19. return 0;
    20. }
    21. int get_month_days(int y,int m){//判断某个月天数
    22. int res=months[m];
    23. if(m==2) res+=is_leap(y);
    24. return res;
    25. }
    26. int get_total_days(int y,int m,int d){//计算第一天到某个日期天数
    27. int res=0;
    28. for(int i=1;i//计算前y-1年的天数
    29. res+=365+is_leap(i);
    30. for(int i=1;i//计算第i年前m-1个月的天数
    31. res+=get_month_days(y,i);
    32. return res+d;//第y年第m月的天数
    33. }
    34. int main()
    35. {
    36. int y1,m1,d1,y2,m2,d2;
    37. while(~scanf("%04d%02d%02d\n%04d%02d%02d",&y1,&m1,&d1,&y2,&m2,&d2))
    38. printf("%d\n",abs(get_total_days(y1,m1,d1)-get_total_days(y2,m2,d2))+1);
    39. return 0;
    40. }

     

    回文日期​​​​​​​

    在日常生活中,通过年、月、日这三个要素可以表示出一个唯一确定的日期。

    牛牛习惯用 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 位数字。

    第一行表示牛牛指定的起始日期 date1,第二行表示牛牛指定的终止日期 date2。保证 date1 和 date2 都是真实存在的日期,且年份部分一定为 4 位数字,且首位数字不为 0。

    保证 date1 一定不晚于 date2。

    输出格式

    输出共一行,包含一个整数,表示在 date1 和 date2 之间,有多少个日期是回文的。

    输入样例:
    1. 20110101
    2. 20111231
    输出样例:
    1

     

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. const int N=5e5+5;
    12. typedef long long LL;
    13. using namespace std;
    14. const int months[]={//平年天数
    15. 0,31,28,31,30,31,30,31,31,30,31,30,31
    16. };
    17. int is_leap(int y){//判断是否为闰年
    18. if(y%100!=0&&y%4==0||y%400==0) return 1;
    19. return 0;
    20. }
    21. int get_month_days(int y,int m){//判断某个月天数
    22. int res=months[m];
    23. if(m==2) res+=is_leap(y);
    24. return res;
    25. }
    26. /*int get_total_days(int y,int m,int d){//计算第一天到某个日期天数
    27. int res=0;
    28. for(int i=1;i
    29. res+=365+is_leap(i);
    30. for(int i=1;i
    31. res+=get_month_days(y,i);
    32. return res+d;//第y年第m月的天数
    33. }*/
    34. bool check(int date){
    35. int year=date/10000;
    36. int month=date%10000/100;
    37. int day=date%100;
    38. if(month<1||month>12) return false;
    39. if(day<1||day>get_month_days(year,month)) return false;
    40. return true;
    41. }
    42. int main()
    43. {
    44. int date1,date2;
    45. cin>>date1>>date2;
    46. int res=0;
    47. for(int i=1000;i<9999;i++){
    48. string a=to_string(i);
    49. string b(a.rbegin(),a.rend());
    50. int date=stoi(a+b);
    51. if(date>=date1&&date<=date2&&check(date))
    52. res++;
    53. }
    54. cout<
    55. return 0;
    56. }

    日期问题​​​​​​​

    小明正在整理一批历史文献。这些历史文献中出现了很多日期。

    小明知道这些日期都在1960年1月1日至2059年12月31日。

    令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。

    更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。

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

    给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?

    输入格式

    一个日期,格式是”AA/BB/CC”。

    即每个’/’隔开的部分由两个 0-9 之间的数字(不一定相同)组成。

    输出格式

    输出若干个不相同的日期,每个日期一行,格式是”yyyy-MM-dd”。

    多个日期按从早到晚排列。

    数据范围

    0≤A,B,C≤9

    输入样例:
    02/03/04
    
    输出样例:
    1. 2002-03-04
    2. 2004-02-03
    3. 2004-03-02
    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. const int N=5e5+5;
    12. typedef long long LL;
    13. using namespace std;
    14. /*const int months[]={//平年天数
    15. 0,31,28,31,30,31,30,31,31,30,31,30,31
    16. };
    17. int is_leap(int y){//判断是否为闰年
    18. if(y%100!=0&&y%4==0||y%400==0) return 1;
    19. return 0;
    20. }
    21. int get_month_days(int y,int m){//判断某个月天数
    22. int res=months[m];
    23. if(m==2) res+=is_leap(y);
    24. return res;
    25. }
    26. int get_total_days(int y,int m,int d){//计算第一天到某个日期天数
    27. int res=0;
    28. for(int i=1;i
    29. res+=365+is_leap(i);
    30. for(int i=1;i
    31. res+=get_month_days(y,i);
    32. return res+d;//第y年第m月的天数
    33. }*/
    34. int a,b,c;
    35. int check(int i,int j,int k)
    36. {
    37. i=i%100;
    38. if(a==i&&b==j&&c==k) return 1;
    39. if(a==j&&b==k&&c==i) return 1;
    40. if(a==k&&b==j&&c==i) return 1;
    41. return 0;
    42. }
    43. int main()
    44. {
    45. scanf("%d/%d/%d",&a,&b,&c);
    46. int month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    47. for(int i=1960;i<=2059;i++){
    48. if((i%4==0&&i%100!=0)||i%400==0){
    49. month[2]=29;
    50. }else{
    51. month[2]=28;
    52. }
    53. for(int j=1;j<=12;j++){
    54. for(int k=1;k<=month[j];k++){
    55. if(check(i,j,k)){
    56. printf("%d-%02d-%02d\n",i,j,k);
    57. }
    58. }
    59. }
    60. }
    61. return 0;
    62. }

     

    回文日期​​​​​​​

    2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。

    因为如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202,恰好是一个回文数。

    我们称这样的日期是回文日期。

    有人表示 20200202 是“千年一遇” 的特殊日子。

    对此小明很不认同,因为不到 22 年之后就是下一个回文日期:20211202 即 2021 年 12 月 2 日。

    也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA 型的回文日期。

    对此小明也不认同,因为大约 100 年后就能遇到下一个 ABABBABA 型的回文日期:21211212 即 2121 年 12 月 12 日。

    算不上“千年一遇”,顶多算“千年两遇”。

    给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个 ABABBABA 型的回文日期各是哪一天。

    注意: 本题数据保证一定有解。

    注意

    下一个回文日期和下一个 ABABBABA 型的回文日期可能是同一天。

    ABABBABA 型的回文日期,需要满足 A≠B。

    输入格式

    输入包含一个八位整数 N,表示日期。

    输出格式

    输出两行,每行 1 个八位数。

    第一行表示下一个回文日期,第二行表示下一个 ABABBABA 型的回文日期。

    数据范围

    对于所有评测用例,10000101≤N≤89991231,保证 N 是一个合法日期的 8 位数表示。

    输入样例:
    20200202
    
    输出样例:
    1. 20211202
    2. 21211212

     

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. const int N=5e5+5;
    12. typedef long long LL;
    13. using namespace std;
    14. const int months[]={//平年天数
    15. 0,31,28,31,30,31,30,31,31,30,31,30,31
    16. };
    17. /*int is_leap(int y){//判断是否为闰年
    18. if(y%100!=0&&y%4==0||y%400==0) return 1;
    19. return 0;
    20. }
    21. int get_month_days(int y,int m){//判断某个月天数
    22. int res=months[m];
    23. if(m==2) res+=is_leap(y);
    24. return res;
    25. }
    26. int get_total_days(int y,int m,int d){//计算第一天到某个日期天数
    27. int res=0;
    28. for(int i=1;i
    29. res+=365+is_leap(i);
    30. for(int i=1;i
    31. res+=get_month_days(y,i);
    32. return res+d;//第y年第m月的天数
    33. }*/
    34. bool check(int date)
    35. {
    36. int year = date / 10000;
    37. int month = date % 10000 / 100;
    38. int day = date % 100;
    39. if(!day || month < 0 || month > 12 ) return false;
    40. if(month != 2 && day >months[month]) return false;
    41. if(month == 2)
    42. {
    43. if((year%4==0&&year%100!=0)||(year%400==0)) //闰年特判
    44. {
    45. if(day > 29) return false;
    46. }
    47. else
    48. {
    49. if(day > 28) return false;
    50. }
    51. }
    52. return true;
    53. }
    54. bool check1(string s)//判断是否是回文日期
    55. {
    56. int len = s.size();
    57. for(int i = 0, j = len - 1; i < j ; i++,j--)//双指针
    58. {
    59. if(s[i] != s[j]) return false;
    60. }
    61. return true;
    62. }
    63. bool check2(string s)//判断是否是ABABBABA型的回文日期
    64. {
    65. if(check1(s))//首先该日期要满足回文格式
    66. {
    67. if(s[0]!=s[2] || s[1]!= s[3] || s[0] == s[1]) return false;
    68. return true;
    69. }
    70. }
    71. int main()
    72. {
    73. int date,flag=0;
    74. cin>>date;
    75. for(int i = date + 1; ;i++)
    76. {
    77. if(check(i))
    78. {
    79. string s = to_string(i);
    80. if(check1(s)&&!flag)//输出回文日期
    81. {
    82. cout<
    83. flag = 1;//标记一下,避免多次输出
    84. }
    85. if(check2(s))//输出ABABBABA 型的回文日期
    86. {
    87. cout<
    88. return 0;
    89. }
    90. }
    91. }
    92. return 0;
    93. }

    日期计算​​​​​​​

    给定一个年份 y 和一个整数 d,问这一年的第 d 天是几月几日?

    注意闰年的 2 月有 29 天。

    满足下面条件之一的是闰年:

    1. 年份是 4 的整数倍,而且不是 100 的整数倍;
    2. 年份是 400 的整数倍。
    输入格式

    输入的第一行包含一个整数 y,表示年份,年份在 1900 到 2015 之间(包含 1900 和 2015)。

    输入的第二行包含一个整数 d,d 在 1 至 365 之间。

    输出格式

    输出两行,每行一个整数,分别表示答案的月份和日期。

    数据范围

    1900≤y≤2015,
    1≤d≤365

    输入样例1:
    1. 2015
    2. 80
    输出样例1:
    1. 3
    2. 21
    输入样例2:
    1. 2000
    2. 40
    输出样例2:
    1. 2
    2. 9

     

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. const int N=5e5+5;
    12. typedef long long LL;
    13. using namespace std;
    14. /*const int months[]={//平年天数
    15. 0,31,28,31,30,31,30,31,31,30,31,30,31
    16. };
    17. int is_leap(int y){//判断是否为闰年
    18. if(y%100!=0&&y%4==0||y%400==0) return 1;
    19. return 0;
    20. }
    21. int get_month_days(int y,int m){//判断某个月天数
    22. int res=months[m];
    23. if(m==2) res+=is_leap(y);
    24. return res;
    25. }
    26. int get_total_days(int y,int m,int d){//计算第一天到某个日期天数
    27. int res=0;
    28. for(int i=1;i
    29. res+=365+is_leap(i);
    30. for(int i=1;i
    31. res+=get_month_days(y,i);
    32. return res+d;//第y年第m月的天数
    33. }*/
    34. int d[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    35. int y,m;
    36. int main()
    37. {
    38. cin>>y>>m;
    39. if(y%4==0&&y%100!=0||y%400==0) d[2]=29;
    40. else d[2]=28;
    41. int x=0;
    42. while(m>0){
    43. if(m-d[x]<=0) break;
    44. else{
    45. m-=d[x];
    46. x++;
    47. }
    48. }
    49. cout<
    50. return 0;
    51. }

  • 相关阅读:
    [C/C++]_[中级]_[static_cast的详细解析]
    ArrayList和LinkedList的区别
    四十、Fluent 颗粒\气泡PBM模型
    AI领域里违规话术如何检测?如何避免直播时违规
    深度寻路四方向
    《Java并发编程的艺术》——锁(笔记)
    【Java面试题】《尚硅谷经典Java面试题第一季(java面试精讲)》学习笔记
    毕业设计--基于SpringBoot+Vue的科研课题项目管理系统
    一文了解ZooKeeper基础命令和应用
    爱上源码,重学Spring MVC深入
  • 原文地址:https://blog.csdn.net/2301_80338843/article/details/136884801