P1217 [USACO1.5]回文质数 Prime Palindromes
标签
题目描述
因为 151 既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 是回文质数。
写一个程序来找出范围 [a,b] (5 \le a < b \le 100,000,000)[a,b](5≤a<b≤100,000,000)( 一亿)间的所有回文质数。
输入格式
第 1 行: 二个整数 a 和 b .
输出格式
输出一个回文质数的列表,一行一个。
输入输出样例
5 500
5 7 11 101 131 151 181 191 313 353 373 383
说明/提示
Hint 1: Generate the palindromes and see if they are prime.
提示 1: 找出所有的回文数再判断它们是不是质数(素数).
Hint 2: Generate palindromes by combining digits properly. You might need more than one of the loops like below.
提示 2: 要产生正确的回文数,你可能需要几个像下面这样的循环。
题目翻译来自NOCOW。
USACO Training Section 1.5
产生长度为5的回文数:
1 for (d1 = 1; d1 <= 9; d1+=2) { // 只有奇数才会是素数 2 for (d2 = 0; d2 <= 9; d2++) { 3 for (d3 = 0; d3 <= 9; d3++) { 4 palindrome = 10000*d1 + 1000*d2 +100*d3 + 10*d2 + d1;//(处理回文数...) 5 } 6 } 7 }
首先,我看了题下面的提示,就想按照提示的方法解这道题。因为右边界的取值范围最大到100000000,所以我考虑到位数可以有以下几种情况:1,3,5,7,9.分类讨论分别写循环就可以列举出这里所有回文数了。
然后因为题目要的是回文质数,所以再加上一个质数的判断函数,是质数就输出就可以了:
按照提示,列举回文数的方法是这样的:
比如说我们需要列举所有九位的回文数,我们需要循环5个数:a,b,c,d,e,把这五个数从0`9进行循环,我们的回文数是这样的:
那就以此类推,写出其他位数的情况:
1 int l,r,num,abc=0; 2 cin >> l >> r; 3 int res[10000]; 4 for (int a = 1; a <= 9; a += 2)//一位 5 { 6 num =a; 7 if (num >= l && num <= r && isp(num)) 8 { 9 res[abc] = num; 10 abc++; 11 } 12 } 13 for (int a = 0; a <= 9; a++)//三位 14 { 15 for (int b = 1; b <= 9; b += 2) 16 { 17 num =b * 100 + a * 10 + b; 18 if (num >= l && num <= r && isp(num)) 19 { 20 res[abc] = num; 21 abc++; 22 } 23 } 24 } 25 for (int a = 0; a <= 9; a++)//五位 26 { 27 for (int b = 0; b <= 9; b++) 28 { 29 for (int c = 1; c <= 9; c += 2) 30 { 31 num = c * 10000 + b * 1000 + a * 100 + b * 10 + c; 32 if (num >= l && num <= r && isp(num)) 33 { 34 res[abc] = num; 35 abc++; 36 } 37 } 38 } 39 } 40 for (int a = 0; a <= 9; a++)//七位 41 { 42 for (int b = 0; b <= 9; b++) 43 { 44 for (int c = 0; c <= 9; c++) 45 { 46 for (int d = 1; d <= 9; d+=2) 47 { 48 num = d * 1000000 + c * 100000 + b * 10000 + a * 1000 + b * 100 + c * 10 + d ; 49 if (num >= l && num <= r && isp(num)) 50 { 51 res[abc] = num; 52 abc++; 53 } 54 } 55 } 56 } 57 } 58 for (int a = 0; a <= 9; a++)//九位 59 { 60 for (int b = 0; b <= 9; b++) 61 { 62 for (int c = 0; c <= 9; c++) 63 { 64 for (int d = 0; d <= 9; d++) 65 { 66 for (int e = 1; e <= 9; e+=2) 67 { 68 num = e * 100000000 + d * 10000000 + c * 1000000 + b * 100000 + a * 10000 + b * 1000 + c * 100 + d * 10 + e; 69 if (num >= l && num <= r && isp(num)) 70 { 71 res[abc] = num; 72 abc++; 73 } 74 } 75 } 76 } 77 } 78 }
质数判断函数:
1 int isp(int a) 2 { 3 for (int i = 2; i <= floor(sqrt(a));i++) 4 { 5 if (a % i == 0) 6 { 7 return 0;//能被整除说明不是质数 8 } 9 } 10 return 1; 11 }
但是这样子储存在数组中的数据顺序有些乱,因为我是按照它中间那一位数的顺序循环的。所以需要排一下序:
1 sort(res, res + abc);
然后就珂以输出了:
1 for (int z = 0; z <= abc-1; z++) 2 { 3 cout << res[z] << endl; 4 }
最后提交上去一看:
WA,WA,WA……
仔细研究程序发现:
回文数不止有奇数位的,还有偶数位的!!!(真是一个惊天动地的珂学大发现呢!)
赶紧加上:
1 for (int b = 0; b <= 9; b++)//六位 2 { 3 for (int c = 0; c <= 9; c++) 4 { 5 for (int d = 1; d <= 9; d += 2) 6 { 7 num = d * 100000 + c * 10000 + b * 1000 +b * 100 + c * 10 + d; 8 if (num >= l && num <= r && isp(num)) 9 { 10 res[abc] = num; 11 abc++; 12 } 13 } 14 } 15 } 16 for (int c = 0; c <= 9; c++)//四位 17 { 18 for (int d = 1; d <= 9; d += 2) 19 { 20 num = d * 1000 + c * 100 + c * 10 + d; 21 if (num >= l && num <= r && isp(num)) 22 { 23 res[abc] = num; 24 abc++; 25 } 26 } 27 } 28 for (int d = 1; d <= 9; d += 2)//两位 29 { 30 num = d * 10 +d; 31 if (num >= l && num <= r && isp(num)) 32 { 33 res[abc] = num; 34 abc++; 35 } 36 }
大功告成!
附上全部的程序:
1 #include2 3 using namespace std; 4 int isp(int a) 5 { 6 for (int i = 2; i <= floor(sqrt(a));i++) 7 { 8 if (a % i == 0) 9 { 10 return 0; 11 } 12 } 13 return 1; 14 } 15 16 int main() 17 { 18 int l,r,num,abc=0; 19 cin >> l >> r; 20 int res[10000]; 21 for (int a = 1; a <= 9; a += 2)//一位 22 { 23 num =a; 24 if (num >= l && num <= r && isp(num)) 25 { 26 res[abc] = num; 27 abc++; 28 } 29 } 30 for (int a = 0; a <= 9; a++)//三位 31 { 32 for (int b = 1; b <= 9; b += 2) 33 { 34 num =b * 100 + a * 10 + b; 35 if (num >= l && num <= r && isp(num)) 36 { 37 res[abc] = num; 38 abc++; 39 } 40 } 41 } 42 for (int a = 0; a <= 9; a++)//五位 43 { 44 for (int b = 0; b <= 9; b++) 45 { 46 for (int c = 1; c <= 9; c += 2) 47 { 48 num = c * 10000 + b * 1000 + a * 100 + b * 10 + c; 49 if (num >= l && num <= r && isp(num)) 50 { 51 res[abc] = num; 52 abc++; 53 } 54 } 55 } 56 } 57 for (int a = 0; a <= 9; a++)//七位 58 { 59 for (int b = 0; b <= 9; b++) 60 { 61 for (int c = 0; c <= 9; c++) 62 { 63 for (int d = 1; d <= 9; d+=2) 64 { 65 num = d * 1000000 + c * 100000 + b * 10000 + a * 1000 + b * 100 + c * 10 + d ; 66 if (num >= l && num <= r && isp(num)) 67 { 68 res[abc] = num; 69 abc++; 70 } 71 } 72 } 73 } 74 } 75 for (int a = 0; a <= 9; a++)//九位 76 { 77 for (int b = 0; b <= 9; b++) 78 { 79 for (int c = 0; c <= 9; c++) 80 { 81 for (int d = 0; d <= 9; d++) 82 { 83 for (int e = 1; e <= 9; e+=2) 84 { 85 num = e * 100000000 + d * 10000000 + c * 1000000 + b * 100000 + a * 10000 + b * 1000 + c * 100 + d * 10 + e; 86 if (num >= l && num <= r && isp(num)) 87 { 88 res[abc] = num; 89 abc++; 90 } 91 } 92 } 93 } 94 } 95 } 96 for (int b = 0; b <= 9; b++)//六位 97 { 98 for (int c = 0; c <= 9; c++) 99 { 100 for (int d = 1; d <= 9; d += 2) 101 { 102 num = d * 100000 + c * 10000 + b * 1000 +b * 100 + c * 10 + d; 103 if (num >= l && num <= r && isp(num)) 104 { 105 res[abc] = num; 106 abc++; 107 } 108 } 109 } 110 } 111 for (int c = 0; c <= 9; c++)//四位 112 { 113 for (int d = 1; d <= 9; d += 2) 114 { 115 num = d * 1000 + c * 100 + c * 10 + d; 116 if (num >= l && num <= r && isp(num)) 117 { 118 res[abc] = num; 119 abc++; 120 } 121 } 122 } 123 for (int d = 1; d <= 9; d += 2)//两位 124 { 125 num = d * 10 +d; 126 if (num >= l && num <= r && isp(num)) 127 { 128 res[abc] = num; 129 abc++; 130 } 131 } 132 sort(res, res + abc); 133 for (int z = 0; z <= abc-1; z++) 134 { 135 cout << res[z] << endl; 136 } 137 return 0; 138 }
还有一个方法。我们其实可以先列举出所有5~100000000的整数,然后分别判断是不是回文数,是不是质数,是不是在区间内。因为会超时,所以……还是别试了……78.42秒……
程序:(其实可以直接用++来列举,我这样进行嵌套是为了能一眼看出效率有多么低)(5 100000000时:)
1 #include2 3 using namespace std; 4 5 int isp(int pr) 6 { 7 for (int i = 2; i <= floor(sqrt(pr)); i++) 8 { 9 if (pr % i == 0) 10 { 11 return 0; 12 } 13 } 14 return 1; 15 } 16 int ishui(int x) 17 { 18 int s=0; 19 if (x % 10 == 0 || x <= 0) 20 { 21 return 0; 22 } 23 while (x > s) 24 { 25 s = s * 10 + x % 10; 26 x /= 10; 27 } 28 if (x == s || s / 10 == x) 29 { 30 return 1; 31 } 32 else 33 { 34 return 0; 35 } 36 } 37 int main() 38 { 39 int s = 0; 40 int l=5, r=100000000; 41 for (int a = 0; a <= 9; a++) 42 { 43 for (int b = 0; b <= 9; b++) 44 { 45 for (int c = 0; c <= 9; c++) 46 { 47 for (int d = 0; d <= 9; d++) 48 { 49 for (int e = 0; e <= 9; e++) 50 { 51 for (int f = 0; f <= 9; f++) 52 { 53 for (int g = 0; g <= 9; g++) 54 { 55 for (int h = 0; h <= 9; h++) 56 { 57 for (int i = 0; i <= 9; i++) 58 { 59 s = a * 100000000 + b * 10000000 + c * 1000000 + d * 100000 + e * 10000 + f * 1000 + g * 100 + h * 10 + i; 60 if (isp(s) && ishui(s) && s >= l && s <= r) 61 { 62 cout << s << endl; 63 } 64 } 65 } 66 } 67 } 68 } 69 } 70 } 71 } 72 } 73 return 0; 74 }