回文质数 USACO

题目描述 Description

因为 151 既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 是回文质数.
写一个程序来找出范围[a,b](5<=a<b<=100,000,000)间的所有回文质数;

因为 151 既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 是回文质数.写一个程序来找出范围[a,b](5<=a<b<=100,000,000)间的所有回文质数;

输入描述 Input Description

*Line 1: a,b

输出描述 Output Description

a与b之间(含)的所有回文质数

一行一个

样例输入 Sample Input

5 500

样例输出 Sample Output

5
7
11
101
131
151
181
191
313
353
373
383

先找回文数,再判断是不是质数。

代碼實現(codevs 38ms,洛谷 44ms):

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 int a,b,c,s;
 5 int hw[300000];
 6 void find(int x){
 7     c=s=x;c/=10;
 8     while(c){s*=10;s+=c%10;c/=10;}//构造奇数数位的回文。 
 9     if(s>b) return;
10     if(s>=a) hw[++hw[0]]=s;//满足条件的回文,录入。 
11     c=s=x;
12     while(c){s*=10;s+=c%10;c/=10;}//构造偶数数位的回文。 
13     if(s>b) return;
14     if(s>=a) hw[++hw[0]]=s;//满足条件的回文,录入。 
15     for(int i=0;i<10;i++) find(10*x+i);//继续寻找。 
16 }
17 int main(){
18     scanf("%d%d",&a,&b);
19     for(int i=1;i<=9;i+=2){
20         s=i;
21         find(i);
22     }
23     sort(hw+1,hw+hw[0]+1);//排序,因为要求顺序输出 
24     for(int i=1;i<=hw[0];i++)
25     for(int j=2;j*j<=hw[i];){
26         if(hw[i]%j==0) break; 
27         j++;
28         if(j*j>hw[i]) printf("%d\n",hw[i]);//输出素数。 
29     }
30     return 0;
31 }

应老师要求,稍微优化了一下(codevs 4ms,洛谷 25ms):

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int maxn=4010;
 5 int a,b,c,s;
 6 int hw[300000];
 7 int zs[maxn],zsm,d,l,re;
 8 char ch[30];
 9 bool v[maxn+10];
10 int read(){
11     l=0,re=0;
12     while(ch[l]=getchar())
13     if(ch[l]>='0'&&ch[l]<='9') break;
14     l++;
15     while(ch[l]=getchar()){
16         if(ch[l]>='0'&&ch[l]<='9') l++;
17         else break;
18     }
19     for(int i=0;i<l;i++) re=re*10+ch[i]-'0';
20     return re;
21 }
22 void write(int x){
23     l=0;
24     while(x){ch[l++]=x%10+'0';x/=10;}
25     for(int i=l-1;i>=0;i--) putchar(ch[i]);
26     putchar('\n');
27 }
28 void find(int x){
29     c=s=x;c/=10;
30     while(c){s*=10;s+=c%10;c/=10;}
31     if(s>b) return;
32     if(s>=a&&(s%11||s==11)) hw[++hw[0]]=s;
33     for(int i=0;i<10;i++) find(10*x+i);
34 }
35 int main(){
36     for(int i=2;i<=maxn;i++)
37     if(!v[i]){
38         zs[zsm++]=i;d=i+i;
39         while(d<=maxn){v[d]=1;d+=i;}
40     }
41     a=read();b=read();
42     for(int i=1;i<=9;i+=2){s=i;find(i);}
43     if(11>=a&&11<=b) hw[++hw[0]]=11;
44     sort(hw+1,hw+hw[0]+1);
45     for(int i=1;i<=hw[0];i++){
46         d=0;
47         while(1){
48             if(hw[i]%zs[d++]==0) break;
49             if(zs[d]*zs[d]>hw[i]||d>zsm){write(hw[i]);break;}
50         }
51     }
52     return 0;
53 }

codevs上跑4ms的不是这段代码,但这段代码理论上更优,可能是评测机不在状态吧。不敢继续攻击网站了。

题目描述

因为151既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 是回文质数。

写一个程序来找出范围[a,b](5 <= a < b <= 100,000,000)( 一亿)间的所有回文质数;

输入输出格式

输入格式:

第 1 行: 二个整数 a 和 b .

输出格式:

输出一个回文质数的列表,一行一个。

输入输出样例

输入样例#1:
5 500
输出样例#1:
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

产生长度为5的回文数:

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;//(处理回文数...)
         }
     }
 }
如果先判素数,再判断是不是回文数会超时。
因为,很明显,素数比回文数多得多。
代码实现(88):
 1 #include<cstdio>
 2 int a,b,c,d,l;
 3 char ch[12];
 4 bool v[100000010];
 5 int main(){
 6     scanf("%d%d",&a,&b);
 7     for(int i=2;i<=b;i++)
 8     if(!v[i]){
 9         c=2*i;d=i;l=0;
10         if(i>=a){
11             for(l=0;l<9;l++){
12                 ch[l]=d%10+'0';d/=10;
13                 if(!d) break;
14             }
15             for(int i=0;i<=l;i++){
16                 if(ch[i]!=ch[l-i]) break;
17                 if(i==l) printf("%s\n",ch);
18             }
19         }
20         while(c<=b){v[c]=1;c+=i;}
21     }
22     return 0;
23 }
应该先找到满足要求的回文数,而后判断其是否为素数。
代码实现(AC):
 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 int a,b,c,s;
 5 int hw[300000];
 6 void find(int x){//find到所有回文数,并存入hw数组。
 7     c=s=x;c/=10;
 8     while(c){s*=10;s+=c%10;c/=10;}
 9     if(s>b) return;
10     if(s>=a) hw[++hw[0]]=s;
11     c=s=x;
12     while(c){s*=10;s+=c%10;c/=10;}
13     if(s>b) return;
14     if(s>=a) hw[++hw[0]]=s;
15     for(int i=0;i<10;i++) find(10*x+i);
16 }
17 int main(){
18     scanf("%d%d",&a,&b);
19     for(int i=1;i<=9;i+=2){
20         s=i;
21         find(i);
22     }
23     sort(hw+1,hw+hw[0]+1);//因为调整回文输入先后太麻烦,所有加了个快排,当然,由于上面的原因,时间上是允许的。
24     for(int i=1;i<=hw[0];i++)
25     for(int j=2;j*j<=hw[i];){
26         if(hw[i]%j==0) break;j++;
27         if(j*j>hw[i]) printf("%d\n",hw[i]);
28     }
29     return 0;
30 }

 有点恶心。

题目来源 CODE[VS],洛谷

posted @ 2017-02-04 10:46  J_william  阅读(744)  评论(0编辑  收藏  举报