技巧:就是偶数位的回文数字一定不是质数---------证明:奇数位之和sum1==偶数位之和sum2的数字可以被11整除。(11除外,这是一个坑点)
最高位,最低位必须是 1, 3, 7, 9
暴力枚举:也就是说,直接枚举奇数位(1,3,5,7)就可以了。至于回文嘛,除去最高位和最低位,也最多是枚举3位数字,时间复杂度在10^3.不管怎么说还是暴力的起的。
线性筛:就是用于判断最后枚举的数字是不是质数的,注意,还是要把质数的范围取大一点。根据质数在后面越来越少的概率图,大家,可以随便定个范围。
最开始,是筛的1000以内的质数,但是,错了很多,所以筛了10000以内的就过了。
ac代码:
#include<iostream> using namespace std; const int N = 1e4; int prime[N], sum, r, l; bool vis[N]; bool is_prime[N]; int a[] = { 1, 3, 7, 9 }; int kk[] = { 5, 7 ,11}; int Prime(int n = N){ int cnt = 0; for (int i = 2; i <= n; ++i) { if (!vis[i]){ prime[cnt++] = i; is_prime[i] = 1; } for (int j = 0; j < cnt&&i*prime[j] <= n; ++j) { vis[i*prime[j]] = 1; if (i%prime[j] == 0)break; } } return cnt; } bool f(int x){ if (x < N)return is_prime[x]; else{ for (int i = 0; i < sum; ++i){ if (x%prime[i] == 0)return 0; } } return 1; } void DFS(){ int num; for (int i = 0; i <= 2;++i) if (kk[i] >= l&&kk[i] <= r)cout << kk[i] << endl; if (r / 100){ for (int i = 0; i <= 3; ++i){ for (int j = 0; j <= 9; ++j){ num = a[i] * 100 + j * 10 + a[i]; if (num>=l&&num<=r&&f(num))cout << num << endl; } } } if (r / 10000){ for (int i = 0; i <= 3; ++i){ for (int a1 = 0; a1 <= 9;++a1) for (int a2 = 0; a2 <= 9; ++a2){ num = a[i] * 10000 + a1 * 1000 + a2 * 100 + a1 * 10 + a[i]; if (num >= l&&num <= r&&f(num))cout << num << endl; } } } if (r / 1000000){ for (int i = 0; i <= 3; ++i){ for (int a1 = 0; a1 <= 9; ++a1) for (int a2 = 0; a2 <= 9; ++a2) for (int a3 = 0; a3 <= 9;++a3){ num = a[i] * 1000000 + a1 * 100000 + a2 * 10000+a3*1000+a2*100 + a1 * 10 + a[i]; if (num >= l&&num <= r&&f(num))cout << num << endl; } } } } int main(){ sum = Prime(); cin >> l >> r; DFS(); }