[USACO1.5]回文质数 Prime Palindromes
题目描述
因为 151 151 151 既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 151 151 是回文质数。
写一个程序来找出范围 [ a , b ] ( 5 ≤ a < b ≤ 100 , 000 , 000 ) [a,b] (5 \le a < b \le 100,000,000) [a,b](5≤a<b≤100,000,000)(一亿)间的所有回文质数。
输入格式
第一行输入两个正整数 a a a 和 b b b。
输出格式
输出一个回文质数的列表,一行一个。
样例 #1
样例输入 #1
5 500
样例输出 #1
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 5 5 的回文数:
for (d1 = 1; d1 <= 9; d1+=2) { // 只有奇数才会是素数
for (d2 = 0; d2 <= 9; d2++) {
for (d3 = 0; d3 <= 9; d3++) {
palindrome = 10000*d1 + 1000*d2 +100*d3 + 10*d2 + d1;//(处理回文数...)
}
}
}
Low Code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int sum;
bool is_prime(int num){ //判断是否为素数
int i;
for(i=2; i*i<=num; i++){
if(num%i == 0) return false;
}
return true;
}
int digits(int num){ //判断是几位数
int res=0;
while(num != 0){
num/=10;
res++;
}
return res;
}
void create_palin(int start, int end, int arr[]){ //把所有回文数装进数组
int digit=0; //digit 当前的回文数位数
digit = digits(start);
int d1, d2, d3, d4;
while(digit <= digits(end)){
for(d1=1; d1<=9; d1++){
if(digit == 1){
arr[++sum]=d1; continue;
}
else if(digit == 2){
arr[++sum] = d1*10 + d1; continue;
}
else
for(d2=0; d2<=9; d2++){
if(digit == 3){
arr[++sum] = d1*100 + d2*10 + d1; continue;
}
else if(digit == 4){
arr[++sum] = d1*1000 + d2*100 + d2*10 + d1; continue;
}
else
for(d3=0; d3<=9; d3++){
if(digit == 5){
arr[++sum] = d1*10000 + d2*1000 + d3*100 + d2*10 +d1; continue;
}
else if(digit==6){
arr[++sum] = d1*100000 + d2*10000 + d3*1000 + d3*100 + d2*10 +d1; continue;
}
for(d4=0; d4<=9; d4++){
if(digit == 7){
arr[++sum] = d1*1000000 + d2*100000 + d3*10000 + d4*1000 + d3*100 + d2*10 +d1; continue;
}
else if(digit == 8){
arr[++sum] = d1*10000000 + d2*1000000 + d3*100000 + d4*10000 + d4*1000 + d3*100 + d2*10 +d1; continue;
}
}
}
}
}
digit++;
}
return ;
}
int main(){
int arr[100000]={0};
int a, b;
scanf("%d %d", &a, &b);
create_palin(a, b, arr); //找到所有[a,b]的回文数
int i;
for(i = 1; i <= sum; i++){
if(arr[i]<=a) continue;
if(arr[i]>=b) return 0;
if(is_prime(arr[i])) //判断回文数是否为素数
printf("%d\n", arr[i]);
}
return 0;
}
Code:
做了优化处理
偶数不是素数 跳过偶数进行判断
偶数位的回文数一定不是素数 跳过最后的8位的数
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int sum;
bool is_prime(int num){ //判断是否是素数
int i;
for(i=3; i*i<=num; i+=2){ //数据从5开始 所以可以从3开始判断 偶数一定不是素数
if(num%i == 0) return false;
}
return true;
}
bool is_palindrome(int num){ //判断是否为回文数
int data=0, temp=num;
while(temp != 0){ //将num倒置
data*=10;
data+=temp%10;
temp/=10;
}
if(data == num) return true;
return false;
}
int main(){
int a, b;
scanf("%d %d", &a, &b) ;
if(b > 10000000) b = 10000000; //偶数位的回文数一定不是素数
if(a%2 == 0) a++; //将a先置为奇数
int i;
for(i = a; i <= b; i+=2){ //偶数不是素数
if(is_palindrome(i) && is_prime(i))
printf("%d\n", i);
}
}