题目链接: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 }