完全日期
友情链接:完全日期
题目:
思路:
直接从20010101
枚举到20211231
,然后再判断每一个数是否是一个合法的日期,如果这个日期是合法的,接着判断这个日期的每一个位置上的数字之和是否是一个完全平方数即可。
判断日期是否合法:
可以使用一个数组来记录所有的月份对应的天数,存在特例:
2
月在闰年的时候是29
天,在平年的时候是28
天。我们可以在每次判断是闰年的时候将数组中2
月份的值更改为29
天,然后判断完后再将其进行恢复为28
天。判断闰年:这个年份能对400整除或者这个年份能对4整除且不能整除100
判断是否是一个完全平方数:
因为对于给定范围的年份,其范围是有限的,对于这道题给出的日期一共有
8
位数,也就是说每个位置上的数最大取的是9
,最小取的是0
,对应的所有位置最大值的和是 8 × 9 8 \times 9 8×9,最小值的和0
,为了更快的知道这个求和出来的值是否是一个完全平方数,我们可以使用一个哈希表将这些值的完全平方数进行存储下来,这样每次查找的时间就变为了 O ( 1 ) O(1) O(1),我们开辟大小为80
的数组内存空间(开80
个大小是因为所有年份的完全平方数的范围为: 0 0 0 ~ 8 × 9 = 72 8 \times 9 = 72 8×9=72),对1 ~ 9
的平方进行标记,表示该范围内的所有完全平方数。
代码:
// 完全日期
#include<iostream>
#include<string>
using namespace std;int hashMap[80]; // 定义一个哈希数组,用于记录完全平方数
int months[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
// 判断闰年
bool judge(int year, int month, int day){// 被400整除,被4整数并不被100整除if(year % 400 == 0 || year % 4 == 0 && year % 100 != 0){months[2] = 29;}if(day > months[month] || day <= 0) return false;months[2] = 28; // 恢复月份的状态return true;
} // 判断完全平方数
bool sqrtNum(int num){int temp = 0;while(num){temp += num % 10;num /=10;}if(hashMap[temp]){ // 查找到这个数是否为一个完全平方数return true;} return false;
}void solve(){const int cl = 20010101;const int cr = 20211231;int year,month,day;int ans = 0;for(int i = 1;i <= 9;i ++){hashMap[i * i] = 1; // 初始化哈希数组}for(int i = cl; i <= cr;i ++){int temp = i;// 首先分割为年月日,不能对i直接进行分割,否则会导致死循环day = temp % 100;temp /= 100;month = temp % 100;if(month <= 0 || month > 12) continue; // 如果月份不合法就直接进行跳过temp /= 100;year = temp;if(judge(year, month, day)){if(sqrtNum(i)){ans++;} }}cout<<ans<<endl;return ;
}int main(){ios::sync_with_stdio(false);cin.tie(0);int t = 1;while(t--){solve();}return 0;
}