非打表解法
听说有人打表过了,果然大佬思维就是不一样
可怜我老老实实用了递归
函数
prime
判断一个数是否是质数
digit_count
返回数字的位数
fun
输出回文质数
代码如下:
#include<iostream>
#include<cmath>
bool prime(int x);
void fun(int n, int x, int sum, int m);
int digit_count(int x);
int y, z;
int main()
{
std::cin >> y >> z;
int a, b;
bool bk = false;
a = digit_count(y);
b = digit_count(z);
a = (a + 2) / 2 + 1;
b = (b + 2) / 2 + 1;
if (y <= 11 && z >= 11)
bk = true;
for (int i = a; i <= b; i++)
{
if (bk && i == 3)
std::cout << 11 << std::endl;
fun(i, 0, i * 2 - 2, 1);
}
}
bool prime(int x)
{
int y, i = 1;
if (x <= 1)
return false;
else if (x == 2)
return true;
else if (x % 2 == 0)
return false;
else for (y = 3; y <= sqrt(x); y += 2)
if (x % y == 0)
return false;
return true;
}
void fun(int n, int x, int sum, int m)
{
n--;
m *= 10;
if (n <= 1)
{
for (int i = 0; i < 10; i++)
{
int j = x + i * m / 10;
if (j > z)
break;
else if (j >= y && prime(j))
std::cout << j << std::endl;
}
}
else for (int i = 0; i < 10; i++)
{
long j = 1;
for (int k = 0; k < sum; k++)
j *= 10;
fun(n, x + i * m / 10 + i * j / m / 10, sum, m);
}
}
int digit_count(int x)
{
int count = 0;
while (x > 0)
{
count++;
x /= 10;
}
return count;
}
注释
首先回文数要是质数的话,它必定是奇数位数(11除外)
否则它必定是11的倍数,所以我们要制造奇数位数的回文数,
再进行是否是质数的判断
控制循环
一位数的回文数要一个循环,两位数和三位数都要两个循环,
所以循环次数等于位数(a+2)/2,fun(int n, int x, int sum, int m)
函数用n来控制递归次数,又由于每次进入函数先进行n的递减,
所以n等于循环次数加1
制造回文
要产生长度为5的回文,类似
10000d1+1000d2+100d3+10d2+d1
其中d1,d2都用了两次,d3只用了一次,那么d3就是递归
结束时最后的循环
由于d1不仅要乘1,还要乘10000,d2不仅要乘10,还要乘1000
(注意d1的1和d2的10这个乘元用fun中的m控制)
要得到d1的10000,即105-1/1,要得到d2的1000即105-1/10
既然如此,就要把5传给递归函数即(回文数位数-1)
(也就是循环次数i*2-2)