考察:枚举
错误思路:
爆搜,结果第九个点TLE.采取多个剪枝依旧第九点TLE....
正确思路:
预处理合法的月+日+年.对于每一个字符串,检查是否有与他在有数字的位数上相同的合法日期,如果有就ans++
坑点:质数不包括1与0,这两个一定要先赋值1!!!!
实测954ms
1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 const int N = 400,M= 10010,S = 60010; 5 int md[N],cnt,prime[M],date[S],tot; 6 bool st[M]; 7 char s[N/10]; 8 int month[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; 9 void GetPrime(int n) 10 { 11 st[1] = st[0] = 1; 12 for(int i=2;i<=n;i++) 13 { 14 if(!st[i]) prime[++cnt] = i; 15 for(int j=1;prime[j]<=n/i;j++) 16 { 17 st[i*prime[j]] =1; 18 if(i%prime[j]==0) break; 19 } 20 } 21 } 22 bool leap(int y) 23 { 24 if(y%400==0) return 1; 25 if(y%4==0&&y%100!=0) return 1; 26 return 0; 27 } 28 bool check(int n) 29 { 30 for(int i=2;i<=n/i;i++) 31 if(n%i==0) return 0; 32 return 1; 33 } 34 void init() 35 { 36 GetPrime(M-1); 37 cnt = 0; 38 for(int i=1;i<=12;i++)//合法的月日 39 for(int j=1;j<=month[i];j++) 40 if(!st[i*100+j]&&!st[j]) md[++cnt] = i*100+j; 41 for(int i=1;i<=9999;i++) 42 if(leap(i)&&check(i*10000+229)) date[++tot] = i*10000+229; 43 for(int i=1;i<=9999;i++) 44 for(int j=1;j<=cnt;j++) 45 if(check(i*10000+md[j])) date[++tot] = i*10000+md[j]; 46 } 47 bool insect(char s[],int d) 48 { 49 int len = strlen(s+1),sl = 8; 50 char op[10]; 51 while(d) 52 { 53 int t = d%10; 54 op[sl] = t+'0'; 55 sl--; 56 d/=10; 57 } 58 while(sl) op[sl--] = '0'; 59 for(int i=1;i<=8;i++) 60 if(s[i]=='-') continue; 61 else if(s[i]!=op[i]) return 0; 62 return 1; 63 } 64 int main() 65 { 66 init(); 67 int T; 68 scanf("%d",&T); 69 while(T--) 70 { 71 int ans = 0; 72 scanf("%s",s+1); 73 int len = strlen(s+1); 74 for(int i=1;i<=tot;i++) 75 if(insect(s,date[i])) ans++; 76 printf("%d\n",ans); 77 } 78 return 0; 79 }