题解
这道题有点意思,原题给了提示的,没看前我是先算质数再做回文判断,
看了提示豁然开朗,先列回文数可以减少质素判断,明显是更明智的做法。
这题思路很清晰的,难点在如何不重不漏构造回文数,构造不同长度的回文数
似乎有点困难,但是固定长度的回文数是不是更好造呢,我们不妨设构造n位长回文函数为deal(n),
只要将其复用就可以解决问题,详见代码。
代码
/*
PROG:pprime
ID:imking022
LANG:C++
*/
#include <iostream>
#include <cstdio>
#include <fstream>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxx = 10;
int a,b;
int cot[maxx];
bool isprm(int num){// 质数判断
for(int i=2;i*i<=num;i++){
if(num%i == 0) return false;
}
return true;
}
bool acc(int n){ // 手动加一
int k,p;
k = (n%2 == 1 ? (n+1) /2 : n/2);
if(cot[k]!=9) cot[k]++;
else{// 遇9进位
p = k;
while(cot[k]==9) k--;
if(k==0) return false;
else if(k==1) cot[k]+=2;
else cot[k]++;
for(int j=k+1;j<=p;j++) cot[j] = 0;
}
return true;
}
void ini(int n){// 预处理 cot = 01000....
memset(cot,0,sizeof(int)*n);
cot[1]=1;
}
void deal(int n){
if(n<2) return;
// init cot
ini(n);
int num,base,k,p;
p = (n%2 == 1 ? (n+1) /2 : n/2);
//main loop
while(true){
num = 0;
for(int i=p; i>0;i--){// 因为是回文数字确定一半即可
num+=cot[i];
if(i!=1) num*=10;
}
base = 1;
for(int i=0;i< n/2 ; i++){// 另一半加上来
k = (num/base)%10;
num += k * pow(10, n-(i+1));
base *=10;
}
if(num>b) break;
// judgement
if(isprm(num) && num>=a)
cout<<num<<endl;
// acc 加一
if(! acc(n) ) break;
}
}
int main(void){
freopen("pprime.in","r",stdin);
freopen("pprime.out","w",stdout);
cin>>a>>b;
int ca,cb,la,lb;// cal for the lengths of a and b
ca = a,cb = b;
la=lb=0;
while(ca>0){
ca/=10;
la++;
}
while(cb>0){
cb/=10;
lb++;
}
for(int k=la;k<=lb;k++){
if(k==1){
for(int i=a;i<10;i++) if(isprm(i)) cout<<i<<endl;
}
else
deal(k);// deal with each length
}
return 0;
}