P5440 【XR-2】奇迹
题目
思路 思维+筛法
第一次做的时候思路是暴力搜索,但是这样在代码上和时间复杂度上都是比较高的,后来看题解才知道可以先打表,虽然打表的题做的很多,但是做这道题还是没有想到,可能在思考上太少了。
我们可以枚举把满足条件的数存储到数组中,然后在对每个输入的数进行检查-
可以代替任何字符,其余位则进行比较,遍历整个数组。
复杂度上是最应该考虑的问题:
初始化打表\(1e5\), 打表完有\(5e4\)满足条件,因为询问\(T \le 10\), 所以加上比较总的复杂度不超过\(5e6\), 做这道题绰绰有余。
Code
#include <iostream>
#include <vector>
using i64 = long long;
int day[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int pday[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
std::vector<int> b, a;
bool prime(int x) {
if(x < 2) return false;
for(int i = 2; i <= x / i; i ++) {
if(x % i == 0) return false;
}
return true;
}
void init() {
for(int i = 1; i <= 12; i ++) {
for(int j = 0; pday[j] <= day[i]; j ++) {
if(prime(i * 100 + pday[j])) {
b.push_back(i * 100 + pday[j]);
}
}
}
for(int i = 1; i <= 9999; i ++) {
if(((!(i % 4) && i % 100) ||!(i % 400)) && prime(i * 10000 + 229)) {
a.push_back(i * 10000 + 229);
}
}
for(int i = 1; i <= 9999; i ++) {
for(int j = 0; j < b.size(); j ++) {
if(prime(i * 10000 + b[j])) {
a.push_back(i * 10000 + b[j]);
}
}
}
}
void solve() {
std::string t;
std::cin >> t;
int ans = 0;
for(int i = 0; i < a.size(); i ++) {
bool flag = 1;
int k = a[i];
for(int j = 7; j >= 0 && flag; j --, k /= 10) {
if(t[j] != '-' && k % 10 != t[j] - '0') {
flag = 0;
}
}
if(flag) ans ++;
}
std::cout << ans << "\n";
}
int main() {
init();
int _;
std::cin >> _;
while(_ --) {
solve();
}
}