6 条题解

  • 2
    @ 2022-10-19 21:13:03

    正解: 枚举后面四位(月份+日期)会更快。

    枚举后四位然后求出整个日期,判断是否在范围内。

    2月不需要判断是否是闰年,因为0229反过来是9220,整个日期是92200229,而9220年是闰年。

    #include<bits/stdc++.h>
    using namespace std;
    int x,y,cnt,month[51]={0,31,29,31,30,31,30,31,31,30,31,30,31};
    int main()
    {
    	cin>>x>>y;
    	for(int i=1;i<=12;i++)
    	{
    		for(int j=1;j<=month[i];j++)  //i是月,j是日 
    		{
    			int c=(j%10)*1000+(j/10)*100+(i%10)*10+i/10;  //将日月反转 
    			int ans=c*10000+i*100+j;  //将年放到前面 
    			if(ans<x || ans>y)continue;  //特判 
    			cnt++;
    		}
    	}
    	cout<<cnt;
    	return 0;
    }
    
    • 1
      @ 2022-9-27 21:52:37

      题解

      思路1

      老老实实,暴力枚举,写就得了。不过由于码量太大,这里不太推荐。

      #include <bits/stdc++.h>
      using namespace std;
      int y_1, m1, d1, y_2, m2, d2, sum = 0; // y1和y2被占用了
      int day[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; //存每个月的天数
      bool check()  
      {  
          return (y_1 < y_2) || ((y_1 == y_2 && m1 < m2) || (y_1 == y_2 && m1 == m2 && d1 <= d2)); //首先,只要现在的年份小于结束年份就一定可以继续循环;然后,如果现在的年份和结束年份相等,且月份小于结束年份也可以循环;最后,只有天数不同,就必须现在的天数小于结束天数。  
      }  
      int r(int x)  
      {  
          return ((x % 4 == 0 && x % 100 != 0) || (x % 400 == 0)) ? 29 : 28; //判断2月的天数  
      }  
      bool palindrome(int y, int m, int d)  
      {  
          char s[8];  
          int t = y * 10000 + m * 100 + d; //将它重新组成日期  
          sprintf(s, "%d", t); //转换为字符  
          for (int i = 0; i < 4; i++)  
              if (s[i] != s[8 - i - 1])  
                  return false;  
          return true; //判断回文 
      }  
      int main()  
      {  
          int t1, t2;  
          scanf("%d%d", &t1, &t2);
          y_1 = t1 / 10000; m1 = t1 / 100 % 100; d1 = t1 % 100; //分离出年份月份和日数  
          y_2 = t2 / 10000; m2 = t2 / 100 % 100; d2 = t2 % 100;  
          while (check()) //判断是否枚举完  
          {  
              bool f = 1; //f用于看是否一已经进行过日期更新  
              if (palindrome(y_1, m1, d1))
                  sum++;  
              if ((m1 == 2 && d1 == r(y_1)) || (m1 != 2 && d1 == day[m1])) //一个月完了  
              {  
                  m1++;  
                  d1 = 1;  
                  f = 0;  
              }  
              if (m1 == 13)
              {  
                  y_1++;  
                  m1 = 1;  
                  d1 = 1;  
                  f = 0;  
              }  
              if (f) //如果月没有结束,就直接加天数即可  
                  d1++;  
          }  
          printf("%d\n", sum); 
          return 0;  
      }
      

      确实可以,但是你不觉得累吗?

      思路2

      我们既然枚举不行,我们就构造吧~

      该如何构造呢?我们可以枚举年份,把年份翻转,此时一定为回文字符串,而且一年只会有一个回文日期,判断日期是否合法就可以了。

      #include <bits/stdc++.h>
      using namespace std;
      string s1, s2;
      int ans;
      bool f(int x)
      {
          if ((x % 4 == 0 && x % 100 != 0) || x % 400 == 0)
              return 1;
          return 0;
      }
      int a[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
      int b[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
      // 两个工具函数
      int ttint(string s)
      {
          int ans = 0, m = 1;
          for (int i = s.length() - 1; i >= 0; i--)
          {
              ans += (s[i] - '0') * m;
              m *= 10;
          }
          return ans;
      }
      string ttstr(int n)
      {
          string ans = "";
          while (n > 0)
          {
              ans = char(n % 10 + '0') + ans;
              n /= 10;
          }
          return ans;
      }
      int main()
      {
          cin >> s1 >> s2; // 必须cin
          // 这里也手动吧
          int start = ttint(s1.substr(0, 4));
          int end = ttint(s2.substr(0, 4));
          for (int i = start; i <= end; i++)
          {
              string s3 = ttstr(i); // 我们这里用手动拆解法
              string s4 = s3;
              reverse(s3.begin(), s3.end()); // 翻转
              s4 = s4 + s3;
              //分离出日和月
              int month = (s4[4] - '0') * 10 + (s4[5] - '0');
              int day = (s4[6] - '0') * 10 + (s4[7] - '0');
              if (s4 > s2 || s4 < s1)
                  continue;
              if (f(i))
              {
                  if (month >= 1 && month <= 12)
                  {
                      if (day >= 0 && day <= b[month])
                      //if嵌套是看翻转的日期是否合法
                          ans++;
                  }
              }
              else
              {
                  if (month >= 1 && month <= 12)
                  {
                      if (day >= 0 && day <= a[month])
                          ans++;
                  }
              }
          }
          printf("%d\n", ans);
          return 0;
      }
      

      思路3

      我们还可以枚举一年中的日期,计算日期的回文,判断年份是否在范围内。当然也有很多细节要注意,比如开始和结束年不完整。

      #include <bits/stdc++.h>
      using namespace std;
      int x, y, cnt = 0;
      int f(int x) // 判断闰年
      {
          if ((x % 4 == 0 && x % 100 != 0) || x % 400 == 0) return 1;
          else return 0;
      }
      int truedate(int x) // 判断日期
      {
          int year = x / 10000, month = (x / 100) % 100, day = x % 100;
          if (month == 0 || month > 12) return 0;
          if ((month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) && day > 31) return 0;
          if ((month == 4 || month == 6 || month == 9 || month == 11) && day > 30) return 0;
          if (!f(year) && month == 2 && day > 28) return 0;
          if (f(year) && month == 2 && day > 29) return 0;
          return 1;
      }
      int main()
      {
          scanf("%d%d", &x, &y);
          int x1 = x / 10000, y1 = y / 10000;
          for (int i = x1; i <= y1; i++)
          {
              int n = i * 10000 + i % 10 * 1000 + i % 100 / 10 * 100 + i % 1000 / 100 * 10 + i / 1000;
              if (truedate(n) && n >= x && n <= y) cnt++; // 日期在范围内
          }
          printf("%d\n", cnt);
          return 0;
      }
      

      ACAC CodeCode 11

      #include <bits/stdc++.h>
      using namespace std;
      int y_1, m1, d1, y_2, m2, d2, sum = 0;
      int day[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
      bool check()  
      {  
          return (y_1 < y_2) || ((y_1 == y_2 && m1 < m2) || (y_1 == y_2 && m1 == m2 && d1 <= d2));
      }  
      int r(int x)  
      {  
          return ((x % 4 == 0 && x % 100 != 0) || (x % 400 == 0)) ? 29 : 28;
      }  
      bool palindrome(int y, int m, int d)  
      {  
          char s[8];  
          int t = y * 10000 + m * 100 + d;
          sprintf(s, "%d", t);
          for (int i = 0; i < 4; i++)  
              if (s[i] != s[8 - i - 1])  
                  return false;  
          return true;
      }  
      int main()  
      {  
          int t1, t2;  
          scanf("%d%d", &t1, &t2);
          y_1 = t1 / 10000; m1 = t1 / 100 % 100; d1 = t1 % 100;
          y_2 = t2 / 10000; m2 = t2 / 100 % 100; d2 = t2 % 100;  
          while (check())
          {  
              bool f = 1;
              if (palindrome(y_1, m1, d1))
                  sum++;  
              if ((m1 == 2 && d1 == r(y_1)) || (m1 != 2 && d1 == day[m1]))
              {  
                  m1++;  
                  d1 = 1;  
                  f = 0;  
              }  
              if (m1 == 13)
              {  
                  y_1++;  
                  m1 = 1;  
                  d1 = 1;  
                  f = 0;  
              }  
              if (f)
                  d1++;  
          }  
          printf("%d\n", sum); 
          return 0;  
      }
      

      ACAC CodeCode 22

      #include <bits/stdc++.h>
      using namespace std;
      string s1, s2;
      int ans;
      bool f(int x)
      {
          if ((x % 4 == 0 && x % 100 != 0) || x % 400 == 0)
              return 1;
          return 0;
      }
      int a[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
      int b[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
      int ttint(string s)
      {
          int ans = 0, m = 1;
          for (int i = s.length() - 1; i >= 0; i--)
          {
              ans += (s[i] - '0') * m;
              m *= 10;
          }
          return ans;
      }
      string ttstr(int n)
      {
          string ans = "";
          while (n > 0)
          {
              ans = char(n % 10 + '0') + ans;
              n /= 10;
          }
          return ans;
      }
      int main()
      {
          cin >> s1 >> s2; // 必须cin
          // 这里也手动吧
          int start = ttint(s1.substr(0, 4));
          int end = ttint(s2.substr(0, 4));
          for (int i = start; i <= end; i++)
          {
              string s3 = ttstr(i);
              string s4 = s3;
              reverse(s3.begin(), s3.end());
              s4 = s4 + s3;
              int month = (s4[4] - '0') * 10 + (s4[5] - '0');
              int day = (s4[6] - '0') * 10 + (s4[7] - '0');
              if (s4 > s2 || s4 < s1)
                  continue;
              if (f(i))
              {
                  if (month >= 1 && month <= 12)
                  {
                      if (day >= 0 && day <= b[month])
                          ans++;
                  }
              }
              else
              {
                  if (month >= 1 && month <= 12)
                  {
                      if (day >= 0 && day <= a[month])
                          ans++;
                  }
              }
          }
          printf("%d\n", ans);
          return 0;
      }
      

      ACAC CodeCode 33

      #include <bits/stdc++.h>
      using namespace std;
      int x, y, cnt = 0;
      int f(int x)
      {
          if ((x % 4 == 0 && x % 100 != 0) || x % 400 == 0) return 1;
          else return 0;
      }
      int truedate(int x)
      {
          int year = x / 10000, month = (x / 100) % 100, day = x % 100;
          if (month == 0 || month > 12) return 0;
          if ((month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) && day > 31) return 0;
          if ((month == 4 || month == 6 || month == 9 || month == 11) && day > 30) return 0;
          if (!f(year) && month == 2 && day > 28) return 0;
          if (f(year) && month == 2 && day > 29) return 0;
          return 1;
      }
      int main()
      {
          scanf("%d%d", &x, &y);
          int x1 = x / 10000, y1 = y / 10000;
          for (int i = x1; i <= y1; i++)
          {
              int n = i * 10000 + i % 10 * 1000 + i % 100 / 10 * 100 + i % 1000 / 100 * 10 + i / 1000;
              if (truedate(n) && n >= x && n <= y) cnt++;
          }
          printf("%d\n", cnt);
          return 0;
      }
      
      • 1
        @ 2022-8-29 14:21:08

        这题我是暴力的做法,首先对于输入的两个字符串,进行了字符串切割,利用了substr函数切割,该函数是从哪个下标开始往后连续几个字符,切割出来利用atoi转成了int类型,得到了两个年份起始和终止,然后我对这两个年份之间的所有年份,翻转后得到一个字符串,此时必然是回文,因此我直接判断这个日期是否合法

        #include <bits/stdc++.h>
        #define ll long long
        using namespace std;
        string s1, s2;
        int ans;
        bool f(int x)
        {
            if (x % 4 == 0 && x % 100 != 0 || x % 400 == 0)
                return 1;
            return 0;
        }
        int a[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        int b[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        int main()
        {
            ios::sync_with_stdio(false);
            cin.tie(0);
            cin >> s1 >> s2;
            int start = atoi(s1.substr(0, 4).c_str());
            int end = atoi(s2.substr(0, 4).c_str());
            for (int i = start; i <= end; i++)
            {
                string stream ss;
                ss << i;
                string s3 = ss.str();
                //上面三行是int直接流转成了字符串。可以自己利用数位拆分的方法实现。
                string s4 = s3;
                reverse(s3.begin(), s3.end());
                s4 = s4 + s3;
                int month = (s4[4] - '0') * 10 + (s4[5] - '0');
                //分离出日和月
                int day = (s4[6] - '0') * 10 + (s4[7] - '0');
                if (s4 > s2 || s4 < s1)
                    continue;
                if (f(i))
                {
                    if (month >= 1 && month <= 12)
                    {
                        if (day >= 0 && day <= b[month])
                        //if嵌套是看翻转的日期是否合法
                            ans++;
                    }
                }
                else
                {
                    if (month >= 1 && month <= 12)
                    {
                        if (day >= 0 && day <= a[month])
                            ans++;
                    }
                }
            }
            cout << ans;
            return 0
        }
        
        • 0
          @ 2023-8-27 9:27:35

          不多说,太简单了(暴力枚举)

              #include<iostream> //基本不需要什么,只需要iostream或者cstdio.就行
          using namespace std;
          int date1,date2,y,m,d,cnt;//cnt记录符合条件的日期数,y是年,m是月,d是日
          bool run_nian (int year){//我懒,我就写了一个判断是否闰年
              if((year%4==0&&year%100!=0)||year%400==0)
                  return true;
              else
                  return false;
          }
          int save(){//获取年月日
              return y*10000+m*100+d;
          }
          int main(){
          	cin>>date1>>date2;
              y=date1/10000;
              m=date1/100%100;
              d=date1%100;
              while(save()<=date2){//枚举
                  int l=10000000,r=1;
                  bool f=1;//提前设置一个f
                  for(int i=1;i<=4;i++){
                      if(save()/l%10!=save()/r%10){
                          f=0;//如果不是回文数那就让f=0,然后退出循环
                          break;
                      }l/=10;
                      r*=10;
                  }
                  if(f)//只要f不是0,cnt就加一
                   	cnt++;
                  if((m==1 || m==3 || m==5 || m==7 || m==8 || m==10 )&&d==31){//别问我12在哪,12月在第42行,它最特殊
                      m++;//31天的
                      d=1;
                  }else if((m==4 || m==6 || m==9 || m==11)&&d==30){
                      m++;//30天的
                      d=1;
                  }else if(m==2&&d==29&&run_nian(y)){//2月的特殊处理
                      m++;//闰年
                      d=1;
                  }else if(m==2&&d==28&& !(run_nian(y))){
                      m++;//平年
                      d=1;
                  }else if(m==12&&d==31){//针对12月的特殊处理
                      y++;
                      m=1;
                      d=1;
                  }else//都没就让d加一
                      d++;
              }cout<<cnt;//输出cnt
              return 0;
          }
          
          • 0
            @ 2023-7-2 23:26:46
            #include <iostream>
            #include <sstream>
            using namespace std;
            int l, r, ans;
            bool huiwen(int x){
                stringstream ss;
                ss << x;
                for (int i = 0; i < 8; i++) if (ss.str()[i] != ss.str()[8 - i - 1]) return false;
                return true;
            }
            int main(){
                cin >> l >> r;
                for (int i = l / 10000; i <= r / 10000; i++){
                    int m = i % 10 * 10 + i / 10 % 10, d = i / 100 % 10 * 10 + i / 1000;
                    if ((m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10 || m == 12) && d <= 31 && huiwen(i * 10000 + m * 100 + d)) ans++;
                    if ((m == 4 || m == 6 || m == 9 || m == 11) && d <= 30 && huiwen(i * 10000 + m * 100 + d)) ans++;
                    if (m == 2)
                        if (i % 400 == 0 || (i % 100 != 0 && i % 4 == 0))
                            if (d <= 29 && huiwen(i * 10000 + m * 100 + d)) ans++;   
                        else 
                            if (d <= 28 && huiwen(i * 10000 + m * 100 + d)) ans++;
                }
                cout << ans;
            }
            
            • 0
              @ 2022-8-29 18:47:12

              先列举年份,再列举月份,然后列举日期,这样做可以减少时间复杂度(就是有些判断有点长……)。

              #include<bits/stdc++.h>
              using namespace std;
              int date1, date2, ans;
              bool hw(int n)
              {
              	return (n / 10000000 == n % 10 && n / 1000000 % 10 == n / 10 % 10 && n / 100000 % 10 == n / 100 % 10 && n / 10000 % 10 == n / 1000 % 10);
              }
              bool rn(int n)
              {
              	return ((n % 4 == 0 && n % 100 != 0) || n % 400 == 0);
              }
              int main()
              {
              	cin >> date1 >> date2;
              	for (int i = date1 / 10000; i <= date2 / 10000; i++)
              	{
              		for (int j = 1; j <= 12; j++)
              		{
              			int x;
              			if (j == 1 || j == 3 || j == 5 || j == 7 || j == 8 || j == 10 || j == 12)
              				x = 31;
              			else if (j > 2)
              				x = 30;
              			else
              			{
              				if (rn(i))
              					x = 29;
              				else
              					x = 28;
              			}
              			for (int k = 1; k <= x; k++)
              				if (hw(i * 10000 + j * 100 + k))
              					ans++;
              		}
              	}
              	cout << ans;
                  return 0;
              }
              
              • 1

              [普及][NOIP2016 普及组] 回文日期

              信息

              ID
              1393
              时间
              1000ms
              内存
              256MiB
              难度
              5
              标签
              递交数
              225
              已通过
              89
              上传者