传送门https://www.luogu.com.cn/problem/P5440
相信奇迹的人,本身就和奇迹一样了不起。——笛亚 《星游记》
思路历程:很离谱的一题,在理论上并不困难,只要简单dfs+欧拉筛就能过。在一开始,我采用了倒着模拟的思路,用stoi函数,强转字符串,发现样例能跑,但是仍旧RE(现在仍未理解这样的原因),于是,我选择了另一种做法,反过来遍历。
下面是代码:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<set>
#include<string>
using namespace std;
const int N=1e8+5;
int _;
string s;
int ans;
bool nums[N];//这两行
long long f[10000001],cot=0;//这两行是欧拉筛的板子
int months[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//减少代码量,开一个月份数组
bool check(int num){//检查年份符不符合逻辑int day=num%100;int month=(num/100)%100;int year=num/10000;if((year%4==0&&year%100!=0)||year%400==0){months[2]=29;}else months[2]=28; return year>=1&&year<=9999&&month>=1&&month<=12&&day>=1&&day<=months[month];
}void dfs(int x,int num){//第x层,数字为numint sum;//记录每一层要加多少if(x==8&&check(num)&&!nums[num]&&!nums[num%10000]&&!nums[num%100]){//100和10000ans++;//2 4 8都要是素数}else if(x==8) return;//只要是8就返回else if(s[x]!='-'){sum=(s[x]-'0')*pow(10,7-x);//字符串转数字 要注意减去‘0’dfs(x+1,num+sum);}else{if(x==4){//特判优化,减少for的遍历(月份)for(int i=0;i<2;++i){sum=i*pow(10,7-x);dfs(x+1,sum+num);}}else if(x==6){//特判优化(日子)for(int i=0;i<4;++i){sum=i*pow(10,7-x);dfs(x+1,sum+num);}}else{for(int i=0;i<=9;++i){sum=i*pow(10,7-x);dfs(x+1,sum+num);}}}}void solve(){ans=0;cin>>s;dfs(0,0);(从第0层开始)cout<<ans<<endl;
}int main(){nums[1]=true;//1不是素数 true就不是素数 long long n=1e8;for(long long i=2;i<=n;i++){if(!nums[i])f[cot++]=i;for(long long j=0;j<cot&&i*f[j]<=n;j++){nums[f[j]*i]=true;if(i%f[j]==0)break;}}//从开头到这里就是一个欧拉筛的板子cin>>_;while(_--){solve(); }return 0;
}