P1217 [USACO1.5]回文质数 Prime Palindromes

题目链接:https://www.luogu.com.cn/problem/P1217

题目分析:

  看着很简单,以为用线性筛筛质数时间复杂度O(n)足够了,但是超时了

超时代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 100000010;
 4 int primes[N], cnt;
 5 bool st[N];
 6 void get_primes(int n) { //线性筛筛质数 
 7     for (int i = 2; i <= n; i++) { 
 8         if (!st[i]) { 
 9             primes[cnt++] = i;
10         }
11         for (int j = 0; primes[j] <= n / i; j++) {
12             st[primes[j] * i] = true;
13             if (i % primes[j] == 0) { 
14                 break;
15             }
16         }
17     }
18 }
19 bool check(int x) { //判断是否是回文数
20     //思路:就是把一个数倒过来,再判断倒过来的数是否和原来的数相等 
21     int y = x, num = 0; //int y = x, 防止x被改变
22     while (y != 0) {
23         num = num * 10 + y % 10; 
24         y /= 10;
25     } 
26     if (num == x) {
27         return true;
28     } else {
29         return false;
30     }
31 }
32 int main() {
33     ios::sync_with_stdio(false);
34     cin.tie(0);
35     cout.tie(0);
36     int a, b;
37     cin >> a >> b;
38     get_primes(b);
39     for (int i = a; i <= b; i++) {
40 
41         if (check(i) && !st[i]) { //是回文数且是质数的话 
42             cout << i << endl;
43         }
44     }
45     return 0;
46 }

然后就新学了一个数学知识:偶数位数回文数(除11)必定不是质数,所以只要运行到9999999 。因为10000000~99999999都是偶数位,

如果其中存在回文数的话,那么一定不是质数。100000000又不是回文数,所以只筛5 ~ 9999999中的质数就可以了。

这个数学性质就是:除 11 外的偶数位回文数,都能被 11 整除

证明:一个整数如果奇数位的数字和等于偶数位的数字和,则其能被11整除。如果一个回文数的长度为偶数,则显然有这个特征。

即:所有偶数位数的回文数都能被11整除。这样所有偶数位数的回文数就都不是质数了,因为有11这个约数了

AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 100000010;
 4 int primes[N], cnt;
 5 bool st[N];
 6 void get_primes(int n) { //线性筛筛质数 
 7     for (int i = 2; i <= n; i++) { 
 8         if (!st[i]) { 
 9             primes[cnt++] = i;
10         }
11         for (int j = 0; primes[j] <= n / i; j++) {
12             st[primes[j] * i] = true;
13             if (i % primes[j] == 0) { 
14                 break;
15             }
16         }
17     }
18 }
19 bool check(int x) { //判断是否是回文数
20     //思路:就是把一个数倒过来,再判断倒过来的数是否和原来的数相等 
21     int y = x, num = 0; //int y = x, 防止x被改变
22     while (y != 0) {
23         num = num * 10 + y % 10; 
24         y /= 10;
25     } 
26     if (num == x) {
27         return true;
28     } else {
29         return false;
30     }
31 }
32 int main() {
33     ios::sync_with_stdio(false);
34     cin.tie(0);
35     cout.tie(0);
36     int a, b;
37     cin >> a >> b;
38     if (b >= 10000000) { //注意此处 
39         b = 9999999;
40     } 
41     get_primes(b);
42     for (int i = a; i <= b; i++) {
43         if (i >= 10000000) { //注意此处 
44             break;
45         }
46         if (check(i) && !st[i]) { //是回文数且是质数的话 
47             cout << i << endl;
48         }
49     }
50     return 0;
51 }
原文地址:https://www.cnblogs.com/fx1998/p/13715051.html