藍橋杯-迴文日期(兩種寫法)

小程xy發表於2024-05-13

在日常生活中,透過年、月、日這三個要素可以表示出一個唯一確定的日期。

牛牛習慣用 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 之間,有多少個日期是迴文的。

輸入樣例:

20110101
20111231

輸出樣例:

1

題解:

一共有兩種寫法:

  1. 列舉前四位數, 後四位是前四位的迴文, 判斷這個日期是否是合法的,以及是否在開始日期和結束日期之間
  2. 列舉後四位數, 前四位是後四位的會問, 判斷這個日期是否在開始日期和結束日期之間

之所以第2種沒有判斷這個日期是否合法, 是因為 後四位是month和day, 它們各個位的資料範圍不超過3, day最大是31, month最大是12, 而前四位各個位最大都可以是9, 所以date一定合法

列舉前四位
ac程式碼👇

#include <bits/stdc++.h>
using namespace std;

int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

bool check(int date)
{
    int year = date / 10000;
    int month = date % 10000 / 100;
    int day = date % 100;
    
    if (month <= 0 || month >= 13 || day <= 0 || day >= 32) return false;

    // 二月需要特殊處理
    // 是閏年, 且2月的day > 29
    if ((year % 2 == 0 && year % 100 != 0 || year % 400 == 0) && month == 2 && day > 29) return false;

    // 不是閏年, 且2月的day > 28
    if (!(year % 2 == 0 && year % 100 != 0 || year % 400 == 0) && month == 2 && day > 28) return false;

    // 除了二月, 其他月份的day大於 days
    if (month != 2 && day > days[month]) return false;
    
    return true;
}

int main()
{
    int a, b; cin >> a >> b;
    
    int res = 0;
    for (int i = 0; i <= 9999; i ++)
    {           // 👇日期的前四位 👇 日期的第五位       👇日期的第6位         👇日期的第7位        👇日期的第8位
        int date = i * 10000 +     1000 * (i % 10) +   100 * (i / 10 % 10) + 10 * (i / 100 % 10) + i / 1000;

        if (date >= a && date <= b && check(date)) res ++;
    }
    
    cout << res << endl;
    return 0;
}

列舉後四位

注意事項:

  • 如果mouth是2並且滿足時迴文的話, 那麼一定是閏年, 因為 mouth是2時的迴文數列中 year的後兩位一定是20, 即 xx20

ac程式碼👇

#include <bits/stdc++.h>
using namespace std;

int days[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int main()
{
    int a, b; cin >> a >> b;
    
    int res = 0;
    for (int mouths = 1; mouths <= 12; mouths ++)
        for (int day = 1; day <= days[mouths]; day ++)
        {               // 👇 取 day 的第一位    👇取day的第二位  👇 取mouths的第一位  👇取mouths的第二位
            int year = 1000 * (day % 10) + 100 * (day / 10) + 10 * (mouths % 10) + mouths / 10;
            int date = year * 10000 + mouths * 100 + day;
            if (date >= a && date <= b) res ++;
        }
    cout << res << endl;
    return 0;
}

覺得寫的不錯的話, 點個贊吧~