A 日期统计 5分
小蓝现在有一个长度为 100 的数组,数组中的每个元素的值都在 0 到 9 的 范围之内。数组中的元素从左至右如下所示:
5 6 8 6 9 1 6 1 2 4 9 1 9 8 2 3 6 4 7 7 5 9 5 0 3 8 7 5 8 1 5 8 6 1 8 3 0 3 7 9 2 7 0 5 8 8 5 7 0 9 9 1 9 4 4 6 8 6 3 3 8 5 1 6 3 4 6 7 0 7 8 2 7 6 8 9 5 6 5 6 1 4 0 1 0 0 9 4 8 0 9 1 2 8 5 0 2 5 3 3
现在他想要从这个数组中寻找一些满足以下条件的子序列:
- 子序列的长度为 8;
- 这个子序列可以按照下标顺序组成一个 yyyymmdd 格式的日期,并且要求这个日期是 2023 年中的某一天的日期,例如 20230902,20231223。yyyy 表示年份,mm 表示月份,dd 表示天数,当月份或者天数的长度只有一位时需要一个前导零补充。
请你帮小蓝计算下按上述条件一共能找到多少个不同 的 2023 年的日期。对于相同的日期你只需要统计一次即可。
思路
这一届的填空题比去年要难上一些, 手算挺容易出错, 还是来写个代码整吧。8层for循环枚举年月日即可。注意闰月和2月的特殊处理, 2023年并不是闰年, 故2月共28天。
通常是用一个数组来表示月份对应天数:
int day[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
去重的话直接用 月份* 100 + 天数 手动hash, 配合 unordered_set。
枚举代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <unordered_set>
#define _for(i, n, m) for (int i = n; i < m; i++)
using namespace std;
int day[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int a[110];
int main()
{
int n = 100;
for (int i = 0; i < n; i++)
cin >> a[i];
unordered_set<int> S;
_for(y1, 0, n)
{
if (a[y1] != 2)
continue;
_for(y2, y1 + 1, n)
{
if (a[y2] != 0)
continue;
_for(y3, y2 + 1, n)
{
if (a[y3] != 2)
continue;
_for(y4, y3 + 1, n)
{
if (a[y4] != 3)
continue;
_for(m1, y4 + 1, n)
{
if (a[m1] > 1)
continue;
_for(m2, m1 + 1, n)
{
int m = a[m1] * 10 + a[m2];
if (m > 12 || !m)
continue;
_for(d1, m2 + 1, n)
{
if (a[d1] > 3)
continue;
_for(d2, d1 + 1, n)
{
int d = a[d1] * 10 + a[d2];
if (d > day[m] || !d)
continue;
if (!S.count(m * 100 + d))
S.insert(m * 100 + d);
// cout << a[y1] << a[y2] << a[y3] << a[y4] << "-" << m << "-" << d << endl;
}
}
}
}
}
}
}
}
cout << S.size() << endl;
return 0;
}