Find the sum of the only eleven primes that are both truncatable from left to right and right to left.
NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes.
3797号有一个有趣的财产。作为素数本身,可以从左到右连续删除数字,并在每个阶段保持素数:3797,797,97和7.同样,我们可以从右到左工作:3797,379,37和3。
找到从左到右和从右到左都可截断的仅有的11个素数之和。
注意:2,3,5和7不被认为是可截断的素数。
思考
1.线性筛实现将素数标记出来,所有素数放在prime[i]的数组前半部分中;
2.是否满足奇怪数字的条件:(1)依次删除末位数 n/10;(2)依次删除首位数 n -= (n%dh)*dh;
3.在素数数组中判断满足条件的数字,并将其加到累加器sum中。
注意:由1开头和结尾的素数都不满足题意,因为1不是素数
#include <stdio.h>
#include <math.h>
#define max 1000000
int prime [max + 5] = {0};
int isprime[max + 5] = {0};
void Prime(){
for(int i = 2; i < max; i++){
if(!prime[i]) {prime[++prime[0]] = i;}
for(int j = 1; j <= prime[0]; j++){
if(prime[j] * i > max) break;
prime[prime[j] * i] = 1;
isprime[prime[j] * i] = 1;
if(i % prime[j] == 0) break;
}
}
}
int isnum(int x){
int num = x;
if(isprime[x] != 0) return 0;//数字本身就不是素数,可省去后面步骤,直接return 0;
if(x % 10 == 1) return 0;//除掉由1开头的数字;
while(x){
x /= 10;
if(isprime[x] != 0) return 0;//prime数组中前半部分已经放入了素数,再次判断是否为素数,用isprime;
}//每次删除末位;
int dh = pow(10, floor(log10(num)));
if(num / dh == 1) return 0;//除掉由1结尾的数字;
while(num){
num -=(num / dh) * dh;
dh /= 10;
if(isprime[num] != 0) return 0;
}//每次删除首位;
return 1;
}
int main(){
Prime();
int flag = 11;
int sum = 0;
for(int i = 5; flag != 0; i++){
if(isnum(prime[i])){
flag--;
sum += prime[i];
printf("%d\n", prime[i]);
}
}
printf("%d\n", sum);
return 0;
}