本题AC的很不容易,断断续续写了一天,遇到很多问题。
题目描述
因为 151 既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 是回文质数。
写一个程序来找出范围 [a,b](5≤a<b≤100,000,000)(一亿)间的所有回文质数。
输入格式
第一行输入两个正整数 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
产生长度为 55 的回文数:
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;//(处理回文数...)
}
}
}
以上是题目给的提示,代码部分我不是很明白,但大概意思就是先找出回文数,再判断质数。
#include<stdio.h>
int count = 0;
int arr[10000] = { 0 }; //数组中元素全部初始化为0
int palindrome(int n) //判断回文数
{
int num = 0;
int temp = n;
while (temp)
{
num = num * 10 + temp%10;
temp /= 10;
}
if (num == n) //逆序数与原数相等,则为回文数
return 1;
else
return 0;
}
int isprime(int n) //判断质数
{
for (int i = 2; i * i <= n; i++)
{
if (n % i == 0)
return 0;
}
return 1;
}
void pd(int n, int m) //先将回文数存放在数组中
{
if (n % 2 == 0) //如果n为偶数,则加一,保证后面循环全为奇数
n++;
if (m > 9999999) //这一步单独说
m = 9999999;
for (int i = 0;;) //i为数组下标
{
for (int j = n; j <= m; j += 2) //j均为奇数,排除偶数,减少循环次数
{
if (palindrome(j)) //判断j是否为回文数
{
arr[i] = j; //将回文数存放在数组中
count++; //计算回文数个数,count初始值为0,方便后面数组输出操作
i++;
}
}
if (arr[i] == 0) //当循环到数组元素为0时,说明回文数已全部存入
break;
}
}
int main()
{
int a, b;
scanf("%d%d", &a, &b);
pd(a, b); //判断回文数
for (int i = 0; i < count; i++)
{
if (isprime(arr[i])) //将数组中的回文数进行质数判断
printf("%d\n", arr[i]);
}
return 0;
}
if (m > 9999999)
m = 9999999;
这一步很容易忽略,少了这步,只能88%。除了11以外,一个数的位数是偶数的话,就不可能为回文数素数。同时限制右边界,可以减少大量循环。
本题需要尽可能地减少循环次数 1.从奇数开始找回文数 2.回文质数没有偶数位