usaco 1.5 pprime 2008.11.5

usaco 1.5 pprime 2008.11.5

这道题有两种思路:

1.   用筛法求出1..1e8范围内的素数,然后判断每个素数是否是回文数。

2.   生成1..1e8范围内的回文数,然后判断它是否是素数。

思路1的复杂度是O(n),思路2的复杂度是O(√n*√n)=O(n),从复杂度来看两种思路没有差别。但思路1用筛法用素数要开O(n)的数组,在n=1e8是就是90M,超出了空间限制,而思路2的空间复杂度是O(1)的,所以我们用思路2。

如何按照从小到大的顺序生成回文数呢? 要从空间和时间去考虑

设生成位数为l的回文数,若l是奇数,那么从小到大枚举(l+1) div 2位的数,然后复制翻转生成一个回文数;若l是偶数,那么从小到大枚举l div 2位的数,然后复制翻转生成一个回文数。上诉两个过程交替进行就可以从小到大生成回文数了。

很有效的优化:任意偶数长度的回文数都不可能为质数(除了11),因为它能被11整除,而11恰好只有自身和1两个因子。

 

program1:ac

{

ID:

PROG: pprime

LANG: PASCAL

}

program p_pprime;
const fin='pprime.in';fout='pprime.out';
var a1,b1,a,b,la,lb,ta,tb,code,h,i:longint;
      pa,pb:string;
      f1,f2:text;
function deal(t:longint):boolean;
var  j:longint;
 begin
   for j:=3 to trunc(sqrt(t)) do
      if t mod j=0 then exit(false);
      deal:=true;
 end;
procedure init;
var k:longint;
  begin
    assign(f1,fin);reset(f1);
    assign(f2,fout);rewrite(f2);
    read(f1,a,b);
    if a mod 2=0 then inc(a);
    if b mod 2=0 then dec(b);
    str(a,pa);str(b,pb);
    la:=length(pa);lb:=length(pb);
    if la mod 2=0 then
         begin
            pa:='1';
            for k:=1 to la do pa:=pa+'0';
            la:=length(pa);
         end;
   if lb mod 2=0 then
        begin
           pb:='';
           for k:=1 to lb-1 do pb:=pb+'9';
           lb:=length(pb);
        end;
   a1:=la div 2+1;b1:=lb div 2+1;
   val(copy(pa,1,a1),ta,code);
   val(copy(pb,1,b1),tb,code);
  end;
  procedure doit;
    var i,j:longint;u,x:string;lu:longint;
        w:boolean;
    begin
       for i:=ta to tb do
       begin
          str(i,u);lu:=length(u);
                 x:=u;
                 for j:=lu-1 downto 1 do x:=x+u[j];
                 val(x,h,code);
                 if (h>=a)and(h<=b) then
                 if h mod 2<>0 then
                  begin
                   w:=deal(h);
                   if w then writeln(f2,x);
                  end;
       end;
   end;
   {--------------------------}
   begin
     init;
     if (a<=11) then
        begin
         for i:=a to 11 do if (deal(i))and(i mod 2<>0) then writeln(f2,i);
         ta:=10;
         la:=2;
        end;
     doit;
     close(f1);
     close(f2);
  end.

program2: 县筛出所有的质数--占太多空间

{

ID:

PROG: pprime

LANG: PASCAL

}

program p_pprime;
const maxn=50000000;
  fin='pprime.in';fout='pprime.out';
var
   f:array[1..maxn]of boolean;
   f1,f2:text;
   a,b,i,j:longint;
procedure init;
    begin assign(f1,fin);reset(f1);
          assign(f2,fout);rewrite(f2);
       read(f1,a,b);
       if a mod 2=0 then inc(a);
       if b mod 2=0 then dec(b);
    end;
procedure shai_a;
var  i,j:longint;
  begin
     fillchar(f,sizeof(f),true);
     for i:=3 to (b div 2) do
       if i mod 2<>0 then
        for j:=2 to (b div i) do
         if j mod 2<>0 then
          f[(i*j-1)div 2]:=false;
  end;
function change(t:longint):boolean;
 var  ch:string;l,j:longint;
 begin
     str(t,ch);l:=length(ch);
     for j:=1 to (l div 2) do
        if ch[j]<>ch[l-j+1] then exit(false);
        change:=true;
end;
  procedure doit;
    var i,p:longint;w:boolean;
     begin
       for p:=(a div 2) to (b div 2) do
         begin i:=2*p+1;
          if f[i] then
              begin
                 w:=change(i);
                 if w then writeln(f2,i);
             end;
         end;
        end;
    {-----------main-------------}
    begin
       init;
       shai_a;
       doit;
       close(f1);
       close(f2);
   end.

program3: 过两组,超时,可能是质数的选择不好,或者应该先生成回文数,在判断其是否未质数

{

ID:

PROG: pprime

LANG: PASCAL

}


program p_pprime;
const
   maxn=100000000;
   fin='pprime.in';fout='pprime.out';
var
   a,b,i,j,a1,b1:longint;
   f1,f2:text;
procedure init;
    begin
       assign(f1,fin);reset(f1);
       assign(f2,fout);rewrite(f2);
       read(f1,a,b);
       if b mod 2=0 then dec(b);
       if a mod 2=0 then inc(a);
       a1:=(a-1)div 2 ;
       b1:=(b-1)div 2;
    end;
function deal(t:longint):boolean;
var  j:longint;
 begin
   for j:=3 to trunc(sqrt(t)) do
      if t mod j=0 then exit(false);
      deal:=true;
 end;
 function change(t:longint):boolean;
 var  ch:string;l,j:longint;
 begin
     str(t,ch);l:=length(ch);
     for j:=1 to (l div 2) do
        if ch[j]<>ch[l-j+1] then exit(false);
        change:=true;
end;
procedure doit;
var k:longint;p,w:boolean;
   begin
      for i:=a1 to b1 do
         begin
            k:=2*i+1;
            p:=deal(k);
            if p then
              begin
                w:=change(k);
                if w then writeln(f2,k);
              end;
         end;
   end;
   {--------------main---------------}
   begin
     init;
     doit;
     close(f1);
     close(f2);
  end.

data

------- test 1 -------

5 500

------- test 2 -------

750 14000

------- test 3 -------

123456 1123456

------- test 4 -------

97000 1299000

------- test 5 -------

9878210 9978210

------- test 6 -------

9902099 9902100

------- test 7 -------

7 10000000

------- test 8 -------

1333331 9743479

------- test 9 -------

5 100000000

 

 

 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值