题目描述 Description
因为151既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 是回文质数。
写一个程序来找出范围[a,b](5 <= a < b <= 100,000,000)( 一亿)间的所有回文质数;
输入输出格式 Input/output
输入格式:
第 1 行: 二个整数 a 和 b .
输出格式:
输出一个回文质数的列表,一行一个。
输入输出样例 Sample input/output
样例测试点#1
输入样例:
5 500
输出样例:
5
7
11
101
131
151
181
191
313
353
373
383
说明 description
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 }
思路:这题难度是有点大,范围竟然有一亿,太坑爹了!所以我对它做了些简化:
①从奇数开始找,每次i=i+2;
②没有偶数位的回文质数,省了一大把时间,真是造福人类啊!
③排除2、5的倍数
每个函数实现过程详解:
①判断回文数:存入一个数组,判断从前往后扫和从后往前扫是否一致。
②判断位数(检测长度是否大于一亿):从前往后扫,返回循环次数就得了。
③判断质数(这个很重要哦):i从3开始,每次i=i+2,再用那个数去试除i,如果刚好除尽,那么就是质数了,返回1。
代码如下:
1 #include <stdio.h> 2 #include <string.h> 3 int huiwen(int k);//判断回文数 4 int hwlength(int k);//计算回文数的长度 5 int prime(int k);//判断质数 6 int main() 7 { 8 int a,b,i,j; 9 scanf("%d%d",&a,&b); 10 for (i=a;i<=b;i++) 11 { 12 if(i%2==0&&i!=2)//排除2的倍数 13 continue; 14 if(i%5==0&&i!=5)//排除5的倍数 15 continue; 16 if(hwlength(i)%2==0&&i!=11)//回文数的长度为偶且不为11 17 continue; 18 if(huiwen(i)!=1)//不是回文直接跳过 19 continue; 20 if(prime(i))//是质数 21 printf("%d\n",i); 22 } 23 return 0; 24 } 25 int huiwen(int k) 26 { 27 int a[10],i=0,j; 28 while(k>0)//每一位存入数组,再判断 29 { 30 a[i]=k%10; 31 k=k/10; 32 i++; 33 } 34 for (j=0;j<i;j++)//两重循环判断(前后后前扫法) 35 if(a[j]!=a[i-j-1])//不是,返回0 36 return 0; 37 return 1;//结束后,是,返回1 38 } 39 int hwlength(int k) 40 { 41 int a[10],i=0; 42 while(k>0) 43 { 44 a[i]=k%10; 45 k/=10; 46 i++; 47 } 48 return (i);//循环了i次 49 } 50 int prime(int k) 51 { 52 int i; 53 for(i=3;i*i<=k;i=i+2)//这样可以减少好多次循环 54 if(k%i==0) 55 { 56 return 0; 57 } 58 return 1; 59 }