题目来源:第十四届蓝桥杯第三期模拟赛
有两种做法,一种是将所有的日期转换成一串数字,依次从 19000101 到 99991231 ,然后判断日期是否存在,然后再计算。第二种方法遍历所有的年份和月份,然后计算出来年份和月份的各个位数的和,之后再看日的有几天是满足上面的要求的。用cnt 数组记录一下即可。代码如下:
#include <bits/stdc++.h>
#define int long long
using namespace std;
constexpr int N = 1e5 + 10;
int month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int cnt[N];
bool check(int year)
{
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
return true;
return false;
}
int get(int x)
{
int res = 0;
while (x > 0)
{
int z = x % 10;
res += z;
x /= 10;
}
return res;
}
void solve()
{
int ans = 0;
for (int i = 1; i <= 28; i ++)
{
int x = get(i);
cnt[x] ++;
}
for (int i = 1900; i <= 9999; i ++)
{
for (int j = 1; j <= 12; j ++)
{
if (j == 2)
{
if (check(i))
{
cnt[11] ++;
int a = get(i), b = 2;
if (a - b > 0) ans += cnt[a - b];
cnt[11] --;
}
else
{
int a = get(i), b = 2;
if (a - b > 0) ans += cnt[a - b];
}
}
else if (month[j] == 31)
{
cnt[11] ++, cnt[3] ++, cnt[4] ++;
int a = get(i), b = get(j);
if (a - b > 0) ans += cnt[a - b];
cnt[11] --, cnt[3] --, cnt[4] --;
}
else if (month[j] == 30)
{
cnt[11] ++, cnt[3] ++;
int a = get(i), b = get(j);
if (a - b > 0) ans += cnt[a - b];
cnt[11] --, cnt[3] --;
}
}
}
cout << ans << "\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
return 0;
}