(特此声明,本题来自于其他学长讲解,并非个人原创,只是整理学习)
一、问题描述
2022 年 2 月 22 日 22: 2022:20 是一个很有意义的时间, 年份为 2022 , 由 3 个 2 和 1 个 0 组成, 如果将月和日写成 4 位, 为 0222 , 也是由 3 个 2 和 1 个 0 组 成, 如果将时间中的时和分写成 4 位, 还是由 3 个 2 和 1 个 0 组成。
小蓝对这样的时间很感兴趣, 他还找到了其它类似的例子, 比如 111 年 10 月 11 日 01: 11,220201:11,2202 年 2 月 22 日 22: 0222:02 等等。
请问, 总共有多少个时间是这种年份写成 4 位、月日写成 4 位、时间写成 4 位后由 3 个一种数字和 1 个另一种数字组成。注意 1111 年 11 月 11 日 11: 1111:11 不算,因为它里面没有两种数字。
二、解题思路
该题采用枚举的算法思想,此题中的特殊时间可以理解为由代表年、月、日的三个四位数字构成,而这三个四位数字均是有两个不同的数字构成,一个数字出现一次,一个数字出现三次;首先,我们要将这两个数字组合一一枚举出来,然后将仅出现一次的数字放置在四位数字四个不同位置上,由于年的范围是从0~9999,所以每一个四位数字均符合条件,月的范围是1~12,日的范围是1~31,时间的范围是小时为0~23,分钟为0~59,在每次数字组合中,将符合年的次数乘以同时符合月和日的日期,再乘以同时符合小时和分钟的次数得到的结果,就是每次数字组合的特殊日期个数。
注:有的同学会想到闰年和二月的问题,但是针对此题是不会造成影响的,假设日为‘29’,那么月就必须是‘22’或者‘99’,显然不符合条件,‘28’同理。
三、代码实现
代码如下(示例):
#include<bits/stdc++.h>
using namespace std;
int main()
{
int cnt = 0;
for( int i = 0; i <= 9 ; ++ i ) //只出现一次的数字
{
for( int j = 0 ; j <= 9 ; ++ j) //出现三次的数字
{
if(i == j)
{
continue;
}
int num[4];
int a = 0, b = 0, c = 0;
for( int pos = 0 ; pos < 4 ; ++ pos) //只出现一次的数字出现的位置
{
for( int k = 0 ; k < 4 ; ++ k)
{
if(k == pos)
{
num[k] = i;
} else {
num[k] = j;
}
}
a++;
int sum = num[3] * 1000 + num[2] * 100 + num[1] * 10 + num[0];
int m = sum / 100, d = sum % 100;
if(m >= 1 && m <= 12 && d >= 1 && d <= 30)
{
b++;
}
if(m >= 0 && m <= 23 && d >= 0 && d <= 59)
{
c++;
}
}
cnt = cnt + a * b * c;
}
}
cout<<cnt<<endl;
return 0;
}