【洛谷】P8716 [蓝桥杯 2020 省 AB2] 回文日期 的题解

【洛谷】P8716 [蓝桥杯 2020 省 AB2] 回文日期 的题解

传送门

思路

这题一眼看上去,有两种解法

枚举合法日期,判断是否为回文数以及属于哪种回文数。

枚举合法回文数,判断是否为合法日期以及属于哪种回文数。

我们先估算一下时间复杂度:

第一种方案,需要枚举年月日+判断回文数,时间复杂度为 O ( n 3 ) O(n^3) O(n3),其实真正的复杂度大约是 O ( 12 × 31 ) n O(12×31)n O(12×31)n

第二种方案,枚举回文数可以枚举一半,另一半转换一下便出来了,只需要判断是否为合法日期。时间复杂度 O ( n ) O(n) O(n)

比较一下两种方法的时间复杂度,不难发现第二种方法更快一点,所以我的思路即是第二种思路。

  1. 首先看到八位的整数,还是回文的,一个一个枚举判断八位数是不是回文的实在是太慢了,最好的方法是自己动手构造。我们只要枚举 1000 1000 1000 8999 8999 8999 这前四位,然后直接构造回文串,存储下来,根据题意查询到即可。

  2. 例如 1001 1001 1001,我们可以构造成 10011001 10011001 10011001 这样的回文串。

  3. 同时我们应该注意,并不一定所有的回文串都符合日期格式,所以需要判断。

  4. 最后按照输入的时间,进去查询就可以,在找到一个 a b a b b a b a ababbaba ababbaba 型的就好。

  5. 一旦考察到年份就要想到闰年这个特殊的东西。

代码

#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <climits>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
#include <ctime>
#include <string>
#include <cstring>
#define lowbit(x) x & (-x)
#define endl "\n"
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
namespace fastIO {
	inline int read() {
		register int x = 0, f = 1;
		register char c = getchar();
		while (c < '0' || c > '9') {
			if(c == '-') f = -1;
			c = getchar();
		}
		while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
		return x * f;
	}
	inline void write(int x) {
		if(x < 0) putchar('-'), x = -x;
		if(x > 9) write(x / 10);
		putchar(x % 10 + '0');
		return;
	}
}
using namespace fastIO;
int b = 1000, e = 9220;
int n;
vector<int> arr;
int month[13] = {0, 31,28,31,30,31,30,31,31,30,31,30,31};
bool check(int yy,int mm,int dd);
void init();
int upper_bound(int key);
int ababbaba(int index);
int main() {
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	int n;
	n = read();
	init();
	int index = upper_bound(n);
	write(arr[index]), putchar('\n');
	index = ababbaba(index);
	write(arr[index]);
	return 0;
}

bool check(int yy, int mm, int dd) {
	if(mm >= 1 && mm <= 12) {
		if((yy % 400 == 0) || (yy % 4 == 0 && yy % 100 != 0)) {
			month[2] = 29;
		}
		if(month[mm] >= dd)
			return true;
		else
			return false;
	}
	return false;
}
void init() {
	for(int i = b; i <= e; i ++) {
		string s = to_string(i);
		for(int j = 3; j >= 0; j --) {
			s += s[j];
		}
		int mm = (s[4] - '0') * 10 + (s[5] - '0');
		int dd = (s[6] - '0') * 10 + (s[7] - '0');
		if(check(i, mm, dd)) {
			int k = stoi(s);
			arr.push_back(k);
		}
		month[2] = 28;
	}
}
int upper_bound(int key) {
	int l, r, mid;
	l = 0, r = arr.size();
	while(l <= r) {
		mid = (l + r) >> 1;
		if(arr[mid] > key)
			r = mid - 1;
		else
			l = mid + 1;
	}
	return l;
}
int ababbaba(int index) {
	for(int i = index; i < arr.size(); i ++) {
		string s = to_string(arr[i]);
		if(s[0] == s[2] && s[1] == s[3])
			return i;
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值