• USACO chapter1


          几天时间就把USACO chapter1重新做了一遍,发现了自己以前许多的不足。蒽,现在的程序明显比以前干净很多,而且效率也提高了许多。继续努力吧,好好的提高自己。这一章主要还是基本功的训练,没多少的思维难度,不过基础也是很重要的。  

    ——2013年11月17日

    1.1.1  Your Ride Is Here

          题目很简单,长字符串读入,按位相乘,同时取模即可,一开始的时候居然忘记了给d1和d2赋值1,结果无论是什么字符串读入计算结果都为0,虽然是水题,还是要记住初始化!

    {ID: jiangyi10
    PROG: ride
    LANG: PASCAL
    }
    
    var
      d1,d2,i,j,k,l,m,n:longint;
      s:ansistring;
    
    {file}
    procedure openf;
    begin
      assign(input,'ride.in'); reset(input);
      assign(output,'ride.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    begin
      {input}
      openf;
    
      {zero}
      d1:=1;
      d2:=1;
    
      {doit}
      readln(s);
      for i:=1 to length(s) do
      d1:=d1*(ord(s[i])-ord('A')+1) mod 47;
      readln(s);
      for i:=1 to length(s) do
      d2:=d2*(ord(s[i])-ord('A')+1) mod 47;
    
      {output}
      if d1=d2 then writeln('GO') else writeln('STAY');
      closef;
    end.
    View Code

    1.1.2  Greedy Gift Givers

          暴力很容易想到,只要每次读入字符串之后循环找到其在字符串数组中的位置即可进行操作,优化的话加入链表hash即可,但是最后经过测试在USACO中暴力也可过,所以略有郁闷。

    {
    ID: jiangyi10
    PROG: gift1
    LANG: PASCAL
    }
    
    var
      now,i,j,k,l,m,n,ave:longint;
      s:array[0..1005] of ansistring;
      amount,ans:array[0..1005] of longint;
    
    {file}
    procedure openf;
    begin
      assign(input,'gift1.in'); reset(input);
      assign(output,'gift1.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    begin
      {openf}
      openf;
      readln(n);
      for i:=1 to n do
      readln(s[i]);
    
      {doit}
      for i:=1 to n do
      begin
        readln(s[0]);
        readln(now,k);
        if k<>0 then ave:=now div k;
        for j:=1 to n do
        if s[j]=s[0] then break;
        amount[j]:=now;
        if k=0 then inc(ans[j],now)
        else inc(ans[j],now mod k);
        for j:=1 to k do
        begin
          readln(s[0]);
          for l:=1 to n do
          if s[l]=s[0] then break;
          inc(ans[l],ave);
        end;
      end;
    
      {output}
      for i:=1 to n do
      writeln(s[i],' ',ans[i]-amount[i]);
      closef;
    end.
    View Code 1
    {
    ID: jiangyi10
    PROG: gift1
    LANG: PASCAL
    }
    const
       modnum=99997;
    type
       link=^node;
       node=record
       t:longint;
       next:link;
    end;
    
    var
      top,ave,i,j,k,l,m,n,t,mo:Longint;
      a:array[0..1005] of ansistring;
      exl:array[0..modnum-1] of link;
      st,en:array[0..1005] of longint;
      s:ansistring;
    
    {file}
    procedure openf;
    begin
      assign(input,'gift1.in'); reset(input);
      assign(output,'gift1.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    {hash}
    function bkdrhash(s:string):longint;
    var
      i:longint;
      ans:int64;
    begin
      ans:=0;
      for i:=1 to length(s) do
      ans:=((ans<<5)+ord(s[i])) and ($FFFFFFF);
      ans:=ans mod modnum;
      exit(ans);
    end;
    
    {find}
    function find(s:string):longint;
    var
      i,j,hash:longint;
      w:link;
    begin
      hash:=bkdrhash(s);
      new(w);
      w:=exl[hash];
      if w=nil then exit(0);
      while (a[w^.t]<>s)and(w^.next<>nil) do w:=w^.next;
      if a[w^.t]=s then exit(w^.t)
      else exit(0);
    end;
    
    {add}
    function add(s:string):longint;
    var
      w:link;
      t,hash,i,j:longint;
    begin
      hash:=bkdrhash(s);
      t:=find(s);
      if t<>0 then exit(t)
         else begin
         new(w);
         inc(top);
         a[top]:=s;
         w^.t:=top;
         w^.next:=exl[hash];
         exl[hash]:=w;
         exit(top);
      end;
    end;
    
    begin
      {input}
      openf;
      readln(n);
      for i:=1 to n do
      begin
        readln(s);
        t:=add(s);
      end;
    
      {doit}
      for i:=1 to n do
      begin
        readln(s);
        k:=find(s);
        readln(st[k],mo);
        if mo=0 then
          inc(en[k],st[k])
        else begin
          ave:=st[k] div mo;
          inc(en[k],st[k] mod mo);
          for j:=1 to mo do
          begin
            readln(s);
            l:=find(s);
            inc(en[l],ave);
          end;
        end;
      end;
    
      {output}
      for i:=1 to n do
      writeln(a[i],' ',en[i]-st[i]);
      closef;
    end.
    View Code 2

    1.1.3  Friday the Thirteenth

          这道题主要考察蔡勒公式,一点意思都没有,注意13月14月代指1,2月,不过呢这道题告诉我重要的一点就是在取模的时候要进行加模后再取模,这样就不会导致负数取模的错误情况。

    {ID: jiangyi10
    PROG: friday
    LANG: PASCAL
    }
    var
      i,j,k,l,m,n:longint;
      year,month,day,date,century:longint;
      ans:array[0..7] of longint; 
    
    {file}  
    procedure openf;
    begin
      assign(input,'friday.in'); reset(input);
      assign(output,'friday.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    {getnum}
    function w(year,month,century:longint):longint;
    begin
      w:=((year+(year div 4)+(century div 4)-2*century+(26*(month+1)div 10)+12)+49) mod 7;
    end;
    
    begin
      {input}
      openf;
      readln(n);
      
      {doit}
      for i:=0 to n-1 do
      begin
        century:=19;
        year:=i;
        while year>=100 do
        begin
          dec(year,100);
          inc(century);
        end;
        for month:=3 to 12 do
        inc(ans[w(year,month,century)]);
        dec(year);
        if year<0 then begin
          inc(year,100);
          dec(century);
        end;
        for month:=13 to 14 do
          inc(ans[w(year,month,century)]);
      end;
      
      {output}
      write(ans[6],' ',ans[0]);
      for i:=1 to 5 do
      write(' ',ans[i]);
      writeln;
      closef;
    end.
    View Code

    1.1.4  Broken Necklace

          首先,这道题目只要对每一个点向前搜索和向后搜索,将两次搜索之和相加即可,然后就过了,但是当数据扩大,连续相同的珠子增多时,这种方法就产生了许多的计算冗余,所以一开始在读入时就可以进行分块处理,将相同颜色的珠子直接分为一块,然后对块进行搜索即可,预计效率可以提高不少。

    {ID: jiangyi10
    PROG: beads
    LANG: PASCAL
    }
    var
      max,i,j,k,l,m,n,behindlength,beforelength:longint;
      s:array[0..10000] of char;
      nowcolor:char;
    procedure openf;
    begin
      assign(input,'beads.in'); reset(input);
      assign(output,'beads.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    procedure searchbehind(x:longint);
    begin
      if behindlength>n then exit;
      if behindlength=0 then nowcolor:=s[x];
      if (nowcolor<>s[x])and(s[x]<>'w')then exit
      else inc(behindlength);
      if x+1<=n then
      searchbehind(x+1)
      else searchbehind(1);
    end;
    procedure searchbefore(x:longint);
    begin
      if beforelength>n then exit;
      if beforelength=0 then nowcolor:=s[x];
      if nowcolor='w' then nowcolor:=s[x];
      if(nowcolor<>s[x])and(s[x]<>'w') then exit
      else inc(beforelength);
      if x-1>0 then
      searchbefore(x-1)
      else searchbefore(n);
    end;
    begin
      openf;
      readln(n);
      max:=0;
      for i:=1 to n do
      read(s[i]);
      for i:=1 to n do
      begin
        behindlength:=0;
        searchbehind(i);
        beforelength:=0;
        if i-1>0 then
        searchbefore(i-1)
        else searchbefore(n);
        if beforelength+behindlength>n then begin
          writeln(n);
          closef;
        end
        else if beforelength+behindlength>max then max:=beforelength+behindlength;
      end;
      writeln(max);
      closef;
    end.
    View Code 1
    {ID: jiangyi10
    PROG: beads
    LANG: PASCAL
    }
    var
      nowcolor,behindlength,beforelength,tmp,max,i,j,k,l,m,n,top,flag:longint;
      a:array[0..355] of char;
      block,color:array[0..355] of longint;
    
    {file}
    procedure openf;
    begin
      assign(input,'beads.in'); reset(input);
      assign(output,'beads.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    {search}
    procedure searchbehind(x:longint);
    begin
      if behindlength>n then exit;
      if behindlength=0 then nowcolor:=color[x];
      if (nowcolor<>color[x])and(color[x]<>0)then exit
      else inc(behindlength,block[x]);
      if x+1<=top then
      searchbehind(x+1)
      else searchbehind(1);
    end;
    procedure searchbefore(x:longint);
    begin
      if beforelength>n then exit;
      if beforelength=0 then nowcolor:=color[x];
      if nowcolor=0 then nowcolor:=color[x];
      if(nowcolor<>color[x])and(color[x]<>0) then exit
      else inc(beforelength,block[x]);
      if x-1>0 then
      searchbefore(x-1)
      else searchbefore(top);
    end;
    
    begin
      {input}
      openf;
      readln(n);
      flag:=0;
      read(a[1]);
      for i:=2 to n do begin
        read(a[i]);
        if a[i]<>a[i-1] then
        begin
          inc(top);
          block[top]:=i-1-flag;
          flag:=i-1;
          if a[i-1]='b' then color[top]:=1;
          if a[i-1]='r' then color[top]:=2;
        end;
      end;
      inc(top);
      block[top]:=n-flag;
      if a[n]='b' then color[top]:=1;
      if a[n]='r' then color[top]:=2;
    
      {special}
      if top=1 then
      begin
        writeln(n);
        closef;
      end;
    
      {doit}
      if color[top]=color[1] then
      begin
        inc(block[1],block[top]);
        dec(top);
      end;
      for i:=1 to top do
      begin
        behindlength:=0;
        searchbehind(i);
        beforelength:=0;
        if i-1>0 then
        searchbefore(i-1)
        else searchbefore(top);
        if behindlength+beforelength>max then max:=behindlength+beforelength;
      end;
    
      {output}
      if max>n then writeln(n) 
      else writeln(max);
      closef;
    end.
    View Code 2

    1.2.1  Milking Cows

         这一题还是很裸的暴力,读入每一个区间,将其按照左端点排序,合并并去重,操作过程中同时统计两个答案,然后就可以AC了。

    {ID: jiangyi10
    PROG: milk2
    LANG: PASCAL
    }
    var
      pre,ans1,ans2,k1,k2,flag,i,j,k,l,m,n:longint;
      st,en:array[0..10005] of longint;
    
    {file}
    procedure openf;
    begin
      assign(input,'milk2.in'); reset(input);
      assign(output,'milk2.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    {sort}
    procedure qsort(l,r:longint);
    var
      i,j,mid,t:longint;
    begin
      i:=l; j:=r;
      mid:=st[l+random(r-l+1)];
      repeat
        while st[i]<mid do inc(i);
        while st[j]>mid do dec(j);
        if i<=j then
        begin
          t:=st[i];
          st[i]:=st[j];
          st[j]:=t;
          t:=en[i];
          en[i]:=en[j];
          en[j]:=t;
          inc(i); dec(j);
        end;
      until i>j;
      if i<r then qsort(i,r);
      if j>l then qsort(l,j);
    end;
    
    begin
      {input}
      openf;
      readln(n);
      for i:=1 to n do
      readln(st[i],en[i]);
    
      {doit}
      randomize;
      qsort(1,n);
      k1:=st[1];
      k2:=en[1];
      ans1:=k2-k1;
      for i:=2 to n do
      begin
        if (st[i]<=k2)and(en[i]>k2) then k2:=en[i];
        if st[i]>k2 then begin
          if k2-k1>ans1 then ans1:=k2-k1;
          if st[i]-k2>ans2 then ans2:=st[i]-k2;
          k1:=st[i]; k2:=en[i];
        end;
      end;
    
      {output}
      writeln(ans1,' ',ans2);
      closef;
    end.
    View Code

    1.2.2  Transformations

          这一题如果去判断要用哪一种方法去实现,就会变得比较困难,那么正难则反,每一种判断是否可行,也就是发现其不可行直接不考虑,最后哪种没有被删去就是这种了。

    {ID: jiangyi10
    PROG: transform
    LANG: PASCAL
    }
    var
      i,j,k,l,m,n:longint;
      c:array[1..7] of boolean;
      a,b,d:array[1..10,1..10] of char;
    
    {file}
    procedure openf;
    begin
      assign(input,'transform.in'); reset(input);
      assign(output,'transform.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    begin
      {input}
      openf;
      fillchar(c,sizeof(c),true);
      readln(n);
      for i:=1 to n do
      begin
         for j:=1 to n do
         read(a[i,j]);
         readln;
      end;
      for i:=1 to n do
      begin
        for j:=1 to n do
        read(b[i,j]);
        readln;
      end;
      
      {doit}
      for i:=1 to n do
      for j:=1 to n do
      begin
        if a[i,j]<>b[i,j] then c[6]:=false;
        if a[i,j]<>b[j,n-i+1] then c[1]:=false;
        if a[i,j]<>b[n-i+1,n-j+1] then c[2]:=false;
        if a[i,j]<>b[n-j+1,i] then c[3]:=false;
        if a[i,j]<>b[i,n-j+1] then c[4]:=false;
      end;
      if c[1] then writeln('1')
      else if c[2] then writeln('2')
      else if c[3] then writeln('3')
      else if c[4] then writeln('4')
      else if c[6] then writeln('6')
      else begin
        fillchar(c,sizeof(c),1);
        for i:=1 to n do
        for j:=1 to n do
        d[i,j]:=a[i,n-j+1];
        for i:=1 to n do
        for j:=1 to n do
        begin
          if d[i,j]<>b[j,n-i+1] then c[1]:=false;
          if d[i,j]<>b[n-i+1,n-j+1] then c[2]:=false;
          if d[i,j]<>b[n-j+1,i] then c[3]:=false;
        end;
        if c[1] or c[2] or c[3] then writeln('5')
        else writeln('7');
      end;
      closef;
    end.
    View Code

    1.2.3  Name That Number

          对于一开始给出的姓名文件,我们先将其保存下来,并重新建立一个数组记录下它的数字。之后读入姓名编号之后再这个数组之中寻找这个数字,每找到一个便输出。

    {ID: jiangyi10
    PROG:namenum
    LANG: PASCAL
    }
    var
      i,j,k,l,m:longint;
      n:int64;
      c:char;
      s:array[1..10000] of string;
      a:array[1..10000] of int64;
      r:longint;
      bo:boolean;
      
    {file}
    procedure openf;
    begin
      assign(input,'namenum.in'); reset(input);
      assign(output,'namenum.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input);
      close(output);
      halt;
    end;
    
    {mi}
    function mi(a,b:int64):int64;
    var
      t,y:int64;
    begin
      t:=1; y:=a;
      while b<>0 do
      begin
        if (b and 1)=1 then t:=t*y;
        y:=y*y;
        b:=b shr 1 ;
        end; exit(t);
    end;
    
    begin
      {input}
      bo:=false;
      assign(input,'dict.txt'); reset(input);
      for i:=1 to 4617 do
      begin
        readln(s[i]);
        for j:=1 to length(s[i]) do
        begin
        if (s[i][j]='A')or(s[i][j]='B')or(s[i][j]='C')then r:=2
        else if (s[i][j]='D')or(s[i][j]='F')or(s[i][j]='E')then r:=3
        else if (s[i][j]='G')or(s[i][j]='H')or(s[i][j]='I')then r:=4
        else if (s[i][j]='J')or(s[i][j]='K')or(s[i][j]='L')then r:=5
        else if (s[i][j]='M')or(s[i][j]='N')or(s[i][j]='O')then r:=6
        else if (s[i][j]='P')or(s[i][j]='R')or(s[i][j]='S')then r:=7
        else if (s[i][j]='T')or(s[i][j]='U')or(s[i][j]='V')then r:=8
        else if (s[i][j]='W')or(s[i][j]='X')or(s[i][j]='Y')then r:=9;
          a[i]:=r*mi(10,length(s[i])-j)+a[i];
        end;
      end;
      close(input);
      openf;
      readln(n);
      
      {output}
      for i:=1 to 4617 do
      if a[i]=n then
      begin
        bo:=true;
        k:=i;
        break;
      end;
      if not bo then writeln('NONE')
      else for i:=k to 4617 do
      begin
      if a[i]=n then
      writeln(s[i]);
      end;
       closef;
    end.
    View Code

    1.2.4  Palindromic Squares

          对于这道题目,枚举1至300,同时计算出平方的进制,判断是否是回文,是则生成那个进制数并输出。在字符串转化时有一个神奇的处理方法,就是定义一个常量字符s=‘0123456789ABCDEFGHIJKLMN’在进制转化时直接取模在s中取位即可。

    {ID: jiangyi10
    PROG: palsquare
    LANG: PASCAL
    }
    var
      i,j,k,l,m,n,o:longint;
      a,b:array[1..10000] of char;
      s:string;
      bo:boolean;
    
    {file}
    procedure openf;
    begin
      assign(input,'palsquare.in'); reset(input);
      assign(output,'palsquare.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    begin
      {input}
      openf;
      readln(n);
      
      {doit}
      s:='0123456789ABCDEFGHIJKL';
      for i:=1 to 300 do
      begin
        bo:=true;
        j:=i*i;
        k:=0;
        o:=0;
        while j<>0 do
        begin
          inc(k);
          a[k]:=s[j mod n+1];
          j:=j div n;
        end;
        for j:=1 to k do
        if a[j]<>a[k-j+1]
          then bo:=false;
        if bo then
        begin
          m:=i;
          while m<>0 do
          begin
            inc(o);
            b[o]:=s[m mod n+1];
            m:=m div n;
          end;
          for j:=o downto 1 do
          write(b[j]);
          write(' ');
          for j:=1 to k do
          write(a[j]);
          writeln;
        end;
      end;
      closef;
    end.
    View Code

    1.2.5  Dual Palindromes

         欣喜地发现这道题和上一道题是一模一样的方法,只要用字符串处理法就可以轻松解决进制转化,剩下的就是模拟了。

    {ID: jiangyi10
    PROG:dualpal
    LANG: PASCAL
    }
    var
      i,j,k,l,m,n,o,p:longint;
      a:array[1..10000] of char;
      s:string;
      bo:boolean;
      
    {openf}
    procedure openf;
    begin
      assign(input,'dualpal.in'); reset(input);
      assign(output,'dualpal.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    begin
      {input}
      openf;
      readln(n,m);
      s:='0123456789ABCDEFGHIJKL';
      
      {doit}
      while n<>0 do
      begin
        inc(m);
        o:=0;
        for i:=2 to 10 do
        begin
          k:=m;
          j:=0;
          while k<>0 do
          begin
            inc(j);
            a[j]:=s[k mod i+1];
            k:=k div i;
          end;
          bo:=true;
          for l:=1 to j do
          if a[l]<>a[j-l+1] then bo:=false;
          if bo then inc(o);
          if o>= 2 then begin
          writeln(m);  dec(n);
          break;
          end;
        end;
        end;
      closef;
    end.
    View Code

    1.3.1  Mixing Milk

         一开始看到题目以为是DP的背包,但是仔细一看,这原来只是一道非常简单的贪心,将数据按照价值排序,从小到大进行处理,最后输出答案即可。

    {ID: jiangyi10
    PROG:milk
    LANG: PASCAL
    }
    var
      ans,i,j,k,l,m,n:longint;
      v,w:array[0..10005] of longint;
    
    {file}
    procedure openf;
    begin
      assign(input,'milk.in'); reset(input);
      assign(output,'milk.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    {sort}
    procedure qsort(l,r:longint);
    var
      i,j,mid,t:longint;
    begin
      i:=l; j:=r;
      mid:=v[l+random(r-l+1)];
      repeat
        while v[i]<mid do inc(i);
        while v[j]>mid do dec(j);
        if i<=j then
        begin
          t:=v[i];
          v[i]:=v[j];
          v[j]:=t;
          t:=w[i];
          w[i]:=w[j];
          w[j]:=t;
          inc(i); dec(j);
        end;
      until i>j;
      if i<r then qsort(i,r);
      if l<j then qsort(l,j);
    end;
    
    begin
      {input}
      openf;
      readln(n,m);
      for i:=1 to m do
      readln(v[i],w[i]);
      randomize;
      qsort(1,m);
    
      {doit}
      i:=0;
      repeat
        inc(i);
        if w[i]<n then begin
          dec(n,w[i]);
          inc(ans,w[i]*v[i]);
        end
        else begin
          inc(ans,n*v[i]);
          n:=0;
        end;
      until n=0;
    
      {output}
      writeln(ans);
      closef;
    end.
    View Code

    1.3.2

         首先根据题目,需要找M块木板,使得其盖住所有有牛的牛棚,所以呢,我们只需关心有牛的牛棚,牛棚总数对于题目没有任何的影响,但是这几块木板怎么找呢,看起来很困难,但是把题目转化一下,求M-1个牛棚之间的空缺,那么就很简单了,快排牛的位置,用最大值减去最小值加1作为答案的初始值,然后对于每两个牛的位置求差,将差排序,从最大开始从答案中减去,最后就得到答案了。需要注意的是当木板的个数大于牛棚(有牛的)个数时,直接输出牛棚个数,一开始没考虑这种特殊情况,结果导致输出了极大的负数,要引以为戒啊。

    {ID: jiangyi10
    PROG:barn1
    LANG: PASCAL
    }
    var
      sum,i,j,k,l,m,n:longint;
      a,b:array[0..205] of longint;
    
    {file}
    procedure openf;
    begin
      assign(input,'barn1.in'); reset(input);
      assign(output,'barn1.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    {sort}
    procedure qsort(l,r:longint);
    var
      i,j,mid,t:longint;
    begin
      i:=l; j:=r;
      mid:=a[l+random(r-l+1)];
      repeat
        while a[i]<mid do inc(i);
        while a[j]>mid do dec(j);
        if i<=j then begin
          t:=a[i];
          a[i]:=a[j];
          a[j]:=t;
          inc(i); dec(j);
        end;
      until i>j;
      if i<r then qsort(i,r);
      if l<j then qsort(l,j);
    end;
    
    begin
      {input}
      openf;
      readln(k,m,n);
      if k>n then begin
        writeln(n);
        closef;
      end;
      for i:=1 to n do
      readln(a[i]);
    
      {doit}
      randomize;
      qsort(1,n);
      sum:=a[n]-a[1]+1;
      for i:=1 to n-1 do
      a[i]:=a[i+1]-a[i];
      qsort(1,n-1);
      for i:=n-1 downto n-k+1 do
      dec(sum,a[i]-1);
    
      {output}
      writeln(sum);
      closef;
    end.
    View Code

    1.3.3  Calf Flac

         这道题思路还是比较清晰的,分奇数串和偶数串讨论,不用删去标点,直接在上面做,遇到标点跳过即可,主要掌握枚举单个点之后向外扩展的思想即可,不过比较坑的地方是输出,特别是计入换行符插入的地方,输出时注意一下。

    {ID: jiangyi10
    PROG:calfflac
    LANG: PASCAL
    }
    var
      ans,i,j,k,l,r,m,n,al,ar,nowl,nowr,temp:longint;
      t,s:ansistring;
      bo:boolean;
      huanhang:array[0..30005] of boolean;
      
    {file}
    procedure openf;
    begin
      assign(input,'calfflac.in'); reset(input);
      assign(output,'calfflac.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    begin
      {input}
      openf;
      readln(s);
      huanhang[length(s)] := true;
      while not eof do
      begin
        readln(t);
        s := s + t;
        huanhang[length(s)] := true;
      end;
      
      {doit}
      s := s + ',.!@#';
      n:=length(s);
      for i:=1 to length(s) do
      begin
        l:=i; r:=i; bo:=true;
        temp:=-1;
        repeat
          if (l>=1)and(r<=n) then
          begin
            al:=0;
            ar:=0;
            while (al=0)and(l>0) do
            begin
              if s[l] in ['a'..'z'] then begin
              al:=ord(s[l])-ord('a')+1;inc(temp);
              end
              else if s[l] in['A'..'Z'] then begin al:=ord(s[l])-ord('A')+1;inc(temp);end
              else dec(l);
            end;
            while (ar=0)and(r<n) do
            begin
              if s[r] in ['a'..'z'] then begin
              ar:=ord(s[r])-ord('a')+1;inc(temp);end
              else if s[r] in ['A'..'Z'] then begin ar:=ord(s[r])-ord('A')+1;inc(temp);end
              else inc(r);
            end;
            if al=ar then
            begin
              if ans<(temp) THEN
              begin ANS:=temp; nowl:=l; nowr:=r;
              end;
            end
            else bo:=false;
          end;
          dec(l); inc(r);
          if (l<1) or (r>n) then bo:=false;
        until bo=false;
        l:=i; r:=i+1; bo:=true;
        temp := 0;
        repeat
          if (l>=1)and(r<=n) then
          begin
            al:=0;
            ar:=0;
            while (al=0)and(l>0) do
            begin
              if s[l] in ['a'..'z'] then begin al:=ord(s[l])-ord('a')+1;inc(temp);end
              else if s[l] in['A'..'Z'] then begin al:=ord(s[l])-ord('A')+1;inc(temp);end
              else dec(l);
            end;
            while (ar=0)and(r<n) do
            begin
              if s[r] in ['a'..'z'] then begin ar:=ord(s[r])-ord('a')+1;inc(temp);end
              else if s[r] in ['A'..'Z'] then begin ar:=ord(s[r])-ord('A')+1;inc(temp);end
              else inc(r);
            end;
            if al=ar then begin
            if ans<(temp) THEN
            begin ANS:=temp; nowr:=r; nowl:=l; end;end
            else bo:=false;
          end;
          dec(l); inc(r);
          if (l<1) or (r>n) then bo:=false;
        until bo=false;
      end;
      writeln(ans);
      
      {output}
      for i:=nowl to nowr do
      begin
      write(s[i]);
      if huanhang[i] then writeln;
      end;
      if huanhang[nowr] = false then writeln;
      closef;
    end.
    View Code

    1.3.4  Prime Cryptarithm

         直接模拟牛式的计算过程,然后判断是否可行,判断可以用集合(set),看计算出的数字是否在集合内。

    {ID: jiangyi10
    PROG:crypt1
    LANG: PASCAL
    }
    var
      se:set of 1..9;
      a:array[1..9] of longint;
      ans,a1,a2,a3,a4,x,a5,i,j,k,l,n:longint;
      s1,s5:array[1..4] of longint;
      s2:array[1..2] of longint;
      s3,s4:array[1..3] of longint;
      bo:boolean;
    
    {file}
    procedure openf;
    begin
      assign(input,'crypt1.in'); reset(input);
      assign(output,'crypt1.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    begin
      {input}
      openf;
      readln(n);
      se:=[];
      for i:=1 to n do
      begin
        read(a[i]);
        se:=se+[a[i]];
      end;
      
      {doit}
      for a1:=1 to n do
        for a2:=1 to n do
          for a3:=1 to n do
            for a4:=1 to n do
              for a5:=1 to n do
              begin
                s1[1]:=a[a1]; s1[2]:=a[a2];
                s1[3]:=a[a3]; s2[1]:=a[a4];
                s2[2]:=a[a5];
                if (s2[1]*s1[1]>=10)or(s2[2]*s1[1]>=10) then continue
                else if(s2[1]*s1[1]+(s2[1]*s1[2])div 10>=10)or(s2[2]*s1[1]+(s2[2]*s1[2])div 10>=10)then continue
                else begin
                  bo:=true;
                  x:=0;
                  s3[3]:=s1[3]*s2[2];
                  x:=s3[3] div 10;
                  s3[3]:=s3[3] mod 10;
                  s3[2]:=s1[2]*s2[2]+x;
                  x:=s3[2] div 10;
                  s3[2]:=s3[2] mod 10;
                  s3[1]:=s1[1]*s2[2]+x;
                  x:=0;
                  s4[3]:=s1[3]*s2[1];
                  x:=s4[3] div 10;
                  s4[3]:=s4[3] mod 10;
                  s4[2]:=s1[2]*s2[1]+x;
                  x:=s4[2] div 10;
                  s4[2]:=s4[2] mod 10;
                  s4[1]:=s1[1]*s2[1]+x;
                  x:=0;
                  s5[4]:=s3[3];
                  s5[3]:=s3[2]+s4[3];
                  x:=s5[3] div 10;
                  s5[3]:=s5[3] mod 10;
                  s5[2]:=s3[1]+s4[2]+x;
                  x:=s5[2] div 10;
                  s5[2]:=s5[2] mod 10;
                  s5[1]:=s4[1]+x;
                  for i:=1 to 3 do
                  begin
                    if(not (s3[i]  in se)) then bo:=false;
                    if(not (s4[i]  in se)) then bo:=false;
                    if(not (s5[i]  in se)) then bo:=false;
                  end;
                  if not(s5[4] in se) then bo:=false;
                  if bo then inc(ans);
                end;
              end;
      
      {output}
      writeln(ans);
      closef;
    end.
    View Code

     1.4.1  Packing Rectangles

          一年前不会,现在依然没有思路,的的确确是模拟但就是分不清情况,只好先跳过,真伤心。

    1.4.2  The Clocks

          将钟的时间抽象为0,1,2,3,直接顺序枚举,加上操作产生值并对4取模,发现所有钟的值为0则方案可行,但是注意每一个指令最多只能执行3次,4次等于没执行,当发现有种方案可行就直接输出,因为是顺序枚举,所以一定是字典序最小的。

    {ID: jiangyi10
    PROG:clocks
    LANG: PASCAL
    }
    const
      a1:array[1..9,0..5] of longint=((4,1,2,4,5,0),
      (3,1,2,3,0,0),(4,2,3,5,6,0),(3,1,4,7,0,0),(5,2,4,5,6,8),
      (3,3,6,9,0,0),(4,4,5,7,8,0),(3,7,8,9,0,0),(4,5,6,8,9,0));
    var
      bo:boolean;
      i,j,k,l,m,n:longint;
      a,c,q:array[1..9] of longint;
      b:array[1..9] of longint;
      q1,q2,q3,q4,q5,q6,q7,q8,q9:longint;
      
    {file}
    procedure openf;
    begin
      assign(input,'clocks.in'); reset(input);
      assign(output,'clocks.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    begin
      {input}
      openf;
      for i:=1 to 9 do
      begin
        read(k);
        if k=3 then a[i]:=1
        else if k=6 then a[i]:=2
        else if k=9 then a[i]:=3
        else a[i]:=4;
      end;
      
      {doit}
      for q1:=0 to 3 do
      for q2:=0 to 3 do
      for q3:=0 to 3 do
      for q4:=0 to 3 do
      for q5:=0 to 3 do
      for q6:=0 to 3 do
      for q7:=0 to 3 do
      for q8:=0 to 3 do
      for q9:=0 to 3 do
      begin
        bo:=true;
        for i:=1 to 9 do
        c[i]:=a[i];
        q[1]:=q1;
        q[2]:=q2;
        q[3]:=q3;
        q[4]:=q4;
        q[5]:=q5;
        q[6]:=q6;
        q[7]:=q7;
        q[8]:=q8;
        q[9]:=q9;
        for i:=1 to 9 do
        while q[i]>0 do
        begin
          for j:=1 to a1[i,0] do
          inc(c[a1[i,j]]);
          dec(q[i]);
        end;
        for i:=1 to 9 do
        if c[i] mod 4 <>0 then bo:=false;
        q[1]:=q1;
        q[2]:=q2;
        q[3]:=q3;
        q[4]:=q4;
        q[5]:=q5;
        q[6]:=q6;
        q[7]:=q7;
        q[8]:=q8;
        q[9]:=q9;
        if bo then
          begin
            if (q[1]<>0) and bo then begin write(1); dec(q[1]); end
            else if (q[2]<>0) and bo then begin write(2); dec(q[2]); end
            else if (q[3]<>0) and bo then begin write(3); dec(q[3]); end
            else if (q[4]<>0) and bo then begin write(4); dec(q[4]); end
            else if (q[5]<>0) and bo then begin write(5); dec(q[5]); end
            else if (q[6]<>0) and bo then begin write(6); dec(q[6]); end
            else if (q[7]<>0) and bo then begin write(7); dec(q[7]); end
            else if (q[8]<>0) and bo then begin write(8); dec(q[8]); end
            else if (q[9]<>0) and bo then begin write(9); dec(q[9]); end;
            for i:=1 to q[1] do write(' ',1);
            if q[2]<>0 then for i:=1 to q2 do write(' ',2);
            if q[3]<>0 then for i:=1 to q3 do write(' ',3);
            if q[4]<>0 then for i:=1 to q4 do write(' ',4);
            if q[5]<>0 then for i:=1 to q5 do write(' ',5);
            if q[6]<>0 then for i:=1 to q6 do write(' ',6);
            if q[7]<>0 then for i:=1 to q7 do write(' ',7);
            if q[8]<>0 then for i:=1 to q8 do write(' ',8);
            if q[9]<>0 then for i:=1 to q9 do write(' ',9);
            writeln;
            closef;
          end;
      end;
    end.
    View Code

    1.4.3  Arithmetic Progressions

          直接暴力枚举每一种情况就可以了,不过需要排序剪枝一下,总的来说没什么技巧性。

    {ID: jiangyi10
    PROG:ariprog
    LANG: PASCAL
    }
    var
      b:array[0..625000]of boolean;
      a:array[0..500000]of longint;
      p,i,j,k,m,n,tot,l:longint;
      ok,bo:boolean;
    
    {file}
    procedure openf;
    begin
      assign(input,'ariprog.in'); reset(input);
      assign(output,'ariprog.out'); rewrite(output);
    end;
    procedure closef;
    begin
       close(input);  close(output);
       halt;
    end;
    
    {sort}
    procedure qsort(l,r:longint);
    var
      i,j,t,mid:longint;
    begin
      i:=l; j:=r;
      mid:=a[l+random(r-l+1)];
      repeat
        while a[i]<mid do inc(i);
        while a[j]>mid do dec(j);
        if i<=j then begin
          t:=a[i];
          a[i]:=a[j];
          a[j]:=t;
          inc(i); dec(j);
        end;
      until i>j;
      if i<r then qsort(i,r);
      if l<j then qsort(l,j);
    end;
    
    {check}
    function check(x,y:longint):boolean;
    var
      i,m:longint;
    begin
      m:=x;
      for i:=1 to n-1 do
      begin
        inc(m,y);
        if not b[m] then exit(false);
      end;
      exit(true);
    end;
    
    begin
      {input}
      openf;
      read(n,m);
    
      {doit}
      for i:=0 to m do
      for j:=i to m do
      begin
        if not b[i*i+j*j] then
        begin
          inc(tot);
          a[tot]:=i*i+j*j;
          b[a[tot]]:=true;
        end;
      end;
      randomize;
      qsort(1,tot);
      l:=2*m*m;
      for i:=1 to 2*m*m div (n-1) do
      begin
        k:=(n-1)*i;
        for j:=1 to tot do
        begin
          if a[j]+k>l then break;
          if check(a[j],i) then begin
            bo:=true;
            writeln(a[j],' ',i);
          end;
        end;
      end;
      if not bo then writeln('NONE');
      closef;
    end.
    View Code

    1.4.4  Mother's Milk

          很纯粹的模拟,对于每一种情况讨论一下,然后深搜求解,对于搜过的情况,用三维数组标记,减少搜索量。

    {ID: jiangyi10
    PROG:milk3
    LANG: PASCAL
    }
    var
      va,vb,vc,na,nb,nc,i,j,k,l,m,n:longint;
      ans:array[0..20] of boolean;
      v:array[0..20,0..20,0..20] of boolean;
    
    {file}
    procedure openf;
    begin
      assign(input,'milk3.in'); reset(input);
      assign(output,'milk3.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    {search}
    procedure search(na,nb,nc:longint);
    begin
      if v[na,nb,nc] then exit else v[na,nb,nc]:=true;
      if na =0 then ans[nc]:=true;
      if (na>0)and(na+nb>vb) then search(na-(vb-nb),vb,nc);
      if (na>0)and(na+nb<=vb) then search(0,na+nb,nc);
      if (nb>0)and(nb+na>va) then search(va,nb-(va-na),nc);
      if (nb>0)and(nb+na<=va) then search(na+nb,0,nc);
      if (nb>0)and(nb+nc>vc) then search(na,nb-(vc-nc),vc);
      if (nb>0)and(nb+nc<=vc) then search(na,0,nb+nc);
      if (nc>0)and(nc+nb>vb) then search(na,vb,nc-(vb-nb));
      if (nc>0)and(nc+nb<=vb) then search(na,nb+nc,0);
      if (nc>0)and(nc+na>va) then search(va,nb,nc-(va-na));
      if (nc>0)and(nc+na<=va) then search(nc+na,nb,0);
      if (na>0)and(na+nc>vc) then search(na-(vc-nc),nb,vc);
      if (na>0)and(na+nc<=vc) then search(na+nc,nb,0);
    end;
    
    begin
      {input}
      openf;
      readln(va,vb,vc);
      
      {doit}
      nc:=vc;
      search(na,nb,nc);
      ans[vc]:=true;
      for i:=0 to 20 do
      if ans[i] then break;
      n:=i; write(i);
      for i:=n+1 to 20 do
      
      {output}
      if ans[i] then write(' ',i);
      writeln;
      closef;
    end.
    View Code

    1.5.1  Number Triangles

          简单的模拟,直接由下往上递推,选取下面最大值累加至上一层,最后输出第一层就是答案了。

    {ID: jiangyi10
    PROG:numtri
    LANG: PASCAL
    }
    var
      i,j,k,l,m,n:longint;
      a:array[0..1005,0..1005] of longint;
    
    {file}
    procedure  openf;
    begin
      assign(input,'numtri.in'); reset(input);
      assign(output,'numtri.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    {max}
    function max(q,w:longint):longint;
    begin
      if q>w then exit(q)
      else exit(w);
    end;
    
    begin
      {input}
      openf;
      readln(n);
      for i:=1 to n do
      for j:=1 to i do
      read(a[i,j]);
      
      {doit}
      for i:=n-1 downto 1 do
      for j:=1 to i do
      inc(a[i,j],max(a[i+1,j],a[i+1,j+1]));
      
      {output}
      writeln(a[1,1]);
      closef;
    end.
    View Code

    1.5.2  Prime Palindromes

          先生成范围内的回文数,之后再判断是否是素数即可,有一个神奇的发现,因为是奇数,所以Miller算法只要判断7和61即可全过,不过保险一点还是加上一些随机。

    {ID: jiangyi10
    PROG:pprime
    LANG: PASCAL
    }
    var
      i,j,k,l:longint;
      w,m,n,ans:int64;
    
    {file}
    procedure openf;
    begin
      assign(input,'pprime.in'); reset(input);
      assign(output,'pprime.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    {power}
    function power(a,b,m:int64):int64;
    var
      y,t:int64;
    begin
      t:=1;
      y:=a;
      while b<>0 do
      begin
        if b and 1=1 then t:=(t*y) mod m;
        y:=y*y mod m;
        b:=b shr 1;
      end;
      exit(t);
    end;
    
    {miller}
    function pan(t:int64):boolean;
    var
      i:longint;
    begin
      for i:=1 to 8 do begin
      w:=random(t-2)+1;
      if power(w,t-1,t)<>1 then exit(false);
      end;
      if power(2,t-1,t)<>1 then exit(false);
      if power(7,t-1,t)<>1 then exit(false);
      if power(61,t-1,t)<>1 then exit(false);
      exit(true);
    end;
    
    begin
      {input}
      openf;
      readln(m,n);
      randomize;
    
      {special}
      if (m<=5) and (n>=5) then writeln('5');
      if (m<=7) and (n>=7) then writeln('7');
      if (m<=11) and (n>=11) then writeln('11');
    
      {3}
      for i:=1 to 9 do
      for j:=0 to 9 do
      if odd(i) then
      begin
        ans:=i*100+j*10+i;
        if (ans<m) or (ans>n)then continue;
        if pan(ans) then writeln(ans);
      end;
    
      {5}
      for i:=1 to 9 do
      for j:=0 to 9 do
      for k:=0 to 9 do
      if odd(i) then
      begin
        ans:=i*10000+j*1000+k*100+j*10+i;
        if (ans<m) or (ans>n) then continue;
        if pan(ans) then writeln(ans);
      end;
    
      {7}
      for i:=1 to 9 do
      for j:=0 to 9 do
      for k:=0 to 9 do
      for l:=0 to 9 do
      if odd(i) then
      begin
        ans:=i*1000000+j*100000+k*10000+l*1000+k*100+j*10+i;
        if (ans<m) or (ans>n) then continue;
        if pan(ans) then writeln(ans);
      end;
      closef;
    end.
    View Code

    1.5.3  Superprime Rib

          由于每一步都要是质数,所以这个数一定由1,3,7,9组成,所以直接搜索这四个数就可以了,关于素数判定同上题,Miller只要7和61就可以全过。

    {ID: jiangyi10
    PROG:sprime
    LANG: PASCAL
    }
    const
      a:array[1..4] of longint=(1,3,7,9);
    var
      ans,i,j,k,l,m,n:longint;
    
    {file}
    procedure openf;
    begin
      assign(input,'sprime.in'); reset(input);
      assign(output,'sprime.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    {power}
    function power(a,b,m:int64):int64;
    var
      y,t:int64;
    begin
      t:=1;
      y:=a;
      while b<>0 do
      begin
        if b and 1=1 then t:=(t*y) mod m;
        y:=y*y mod m;
        b:=b shr 1;
      end;
      exit(t);
    end;
    
    {miller}
    function pan(t:int64):boolean;
    var
      i:longint;
    begin
      if power(7,t-1,t)<>1 then exit(false);
      if power(61,t-1,t)<>1 then exit(false);
      exit(true);
    end;
    
    {search}
    procedure search(m,x:longint);
    var
      i,j,k,l:longint;
    begin
      if x=n then begin
        writeln(m);
        exit;
      end;
      for i:=1 to 4 do
      begin
        ans:=m*10+a[i];
        if pan(ans) then search(ans,x+1);
      end;
    end;
    
    begin
      {input}
      openf;
      readln(n);
    
      {special}
      if n=1 then begin
        writeln(2);
        writeln(3);
        writeln(5);
        writeln(7);
      end;
    
      {doit}
      if n>=2 then begin
        search(2,1);
        search(3,1);
        search(5,1);
        search(7,1);
      end;
      closef;
    end.
    View Code

    1.5.4  checker

          对于方案输出,可以直接搜索,像一般的八皇后问题一样,但是对于方案数,这样肯定会超时,所以,要用上位运算来优化,Martrix神牛的方法不管什么时候看都还是那么高级,用了位运算,巧妙地利用了搜索的有序性来加速,比dancinglink快多了。

    {ID: jiangyi10
    PROG:checker
    LANG: PASCAL
    }
    var
      num,sum,a,x,i,j,k,l,m,n:longint;
      ans:array[1..100] of longint;
      b,c,d:array[-100..1000] of boolean;
    
    {file}
    procedure openf;
    begin
      assign(input,'checker.in'); reset(input);
      assign(output,'checker.out'); rewrite(output);
    end;
    procedure closef;
    begin
      close(input); close(output);
      halt;
    end;
    
    {queen}
    procedure queen(row,ld,rd:longint);
    var
      pos,p:longint;
    begin
      if row<>x then
      begin
        pos:=x and not (row or ld or rd);
        while pos<>0 do
        begin
          p:=pos and -pos;
          pos:=pos-p;
          queen(row+p,(ld+p)shl 1,(rd+p)shr 1);
        end;
      end
      else inc(sum);
    end;
    
    {print}
    procedure print;
    var
      i:longint;
    begin
      for i:=1 to n-1 do
      write(ans[i],' ');
      writeln(ans[n]);
      if num=3 then begin
      writeln(sum);
      closef;
      end;
    end;
    
    {search}
    procedure search(t:longint);
    var
      j:longint;
    begin
      if t> n then
      begin
        inc(num);
        if num<= 3 then print;
        exit;
      end;
      for j:=1 to n do
      if b[j] and c[t+j] and d[t-j] then
      begin
        ans[t]:=j;
        b[j]:=false;
        c[t+j]:=false;
        d[t-j]:=false;
        search(t+1);
        b[j]:=true;
        c[j+t]:=true;
        d[t-j]:=true;
      end;
    end;
    
    begin
      {input}
      openf;
      fillchar(c,sizeof(c),true);
      fillchar(b,sizeof(b),true);
      fillchar(d,sizeof(d),true);
      readln(n);
      x:=((1 shl n)-1);
      
      {doit}
      queen(0,0,0);
      search(1);
    end.
    View Code

    愿你出走半生,归来仍是少年

  • 相关阅读:
    Python DayDayUp系列 —— 字符串操作(一)
    Condition对象以及ArrayBlockingQueue阻塞队列的实现(使用Condition在队满时让生产者线程等待, 在队空时让消费者线程等待)
    ReadWriteLock: 读写锁
    优秀的github项目学习
    synchronized:内部锁
    ReentreantLock:重入锁
    好的文章
    Java内存模型与volatile关键字
    GitHub远程库的搭建以及使用
    使用Executor框架创建线程池
  • 原文地址:https://www.cnblogs.com/forever97/p/3427922.html
Copyright © 2020-2023  润新知