题目
2018年10月2日是一个神奇的日子,因为将数字连起来就变成了2018102,2018102是一个正读倒读都一样的整数。
那么,问题来了,从公元1年1月1日到x年y月z日,有多少个这样神奇的日子?
注意:对于任意一天,a年b月c日中的a, b, c这三个数都不能有前导零,且要求是合法的日子。别忘记考虑闰年。
题目链接
https://citel.bjtu.edu.cn/acm/problem/1862
输入数据
三个整数 x, y, z (1≤x≤2018, 1≤y≤12, 1≤z≤31)
表示x年y月z日,保证日期合法。
输出数据
回文日期的个数(一个整数)。
样例输入
1000 1 1
样例输出
1487
问题分析
从 111 枚举到 xyz,判断是否是回文数即可。怎么判断回文数呢,可以把数字反转然后判断是否和原数字相等,也可以从首尾开始逐个判断对称位置的数字是否相等。不过要注意每个月份有几天以及闰年的问题。
30天:4月、6月、9月、11月
31天:1月、3月、5月、7月、8月、10月、12月
注意2月份在平年有28天,闰年有29天。
闰年的定义是:(能被4整除但不能被100整除)或能被400整除
我的基本思路是先把数字转成字符串,然后通过判断字符串对称位置的字符是否相同来确定是否是回文数。
AC代码
#include <bits/stdc++.h>
using namespace std;
int huiwen(string s)
{
int i, j;
string s2 = s;
for (i = 0, j = s2.length() - 1; i < s.length(); i++, j--)
if (s[i] != s2[j])
return 0;
return 1;
}
string int_string(int n)
{
char cs[100];
sprintf(cs, "%d", n);
return string(cs);
}
int main()
{
string s;
int x, y, z, k, i, j, ans = 0;
cin >> x >> y >> z;
for (i = 1; i < x; i++)
{
for (j = 1; j <= 12; j++)
{
for (k = 1; k <= 31; k++)
{
if (k == 31 && (j == 4 || j == 6 || j == 9 || j == 11))
continue;
if (j == 2 && (k == 30 || k > 28 && !((i % 4 == 0 && (i % 100)) || (i % 400 == 0))))
break;
s = int_string(i) + int_string(j) + int_string(k);
if (huiwen(s))
ans++;
}
}
}
for (i = x, j = 1; j < y; j++)
{
for (k = 1; k <= 31; k++)
{
if (k == 31 && (j == 4 || j == 6 || j == 9 || j == 11))
continue;
if (j == 2 && (k == 30 || k > 28 && !((i % 4 == 0 && (i % 100)) || (i % 400 == 0))))
break;
s = int_string(i) + int_string(j) + int_string(k);
if (huiwen(s))
ans++;
}
}
for (i = x, j = y, k = 1; k <= z; k++)
{
if (k == 31 && (j == 4 || j == 6 || j == 9 || j == 11))
continue;
if (j == 2 && (k == 30 || k > 28 && !((i % 4 == 0 && (i % 100)) || (i % 400 == 0))))
break;
s = int_string(i) + int_string(j) + int_string(k);
if (huiwen(s))
ans++;
}
cout << ans << endl;
return 0;
}