回文质数 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],洛谷

转载于:https://www.cnblogs.com/J-william/p/6160855.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值