POJ 1611(并查集)

唯一的WA

是把0的父亲当成祖先

father[x]getfather(x)差别巨大啊

Program p1611;
const
   maxn=30010;
   maxm=500;
var
   n,m,i,j,k,p1,p2,ans,f0:longint;
   father:array[0..maxn] of longint;
function getfather(x:longint):longint;
begin
   if father[x]=x then exit(x);
   father[x]:=getfather(father[x]);
   exit(father[x]);
end;
procedure union(x,y:longint);
begin
   if getfather(x)<>getfather(y) then
      father[father[x]]:=father[father[y]];
end;
begin
   read(n,m);
   while (n+m>0) do
   begin
      for i:=0 to n-1 do father[i]:=i;
      for i:=1 to m do
      begin
         read(k);
         if k>0 then read(p1);
         if k>1 then
            for j:=2 to k do
            begin
               read(p2);
               union(p1,p2);
            end;
      end;
      ans:=1;
      f0:=getfather(0);
      for i:=1 to n-1 do if getfather(i)=f0 then inc(ans);
      writeln(ans);
      read(n,m);
   end;
end.

POJ 2271(HTML)

这题字符串处理

注意Seekeof会自动把后面的空格吃掉(有时遇到回车,后面会漏一个空格……貌似有时没空格也会读到,字符串处理时慎用

另外 空格的Ascii码是32,31及以下都是不可输入字符

program P2271;
var
   s:string;
procedure cin;
var
   c:char;
   i,len:longint;
begin
   s:='';
   c:=' ';
   i:=0;
   while not(seekeof) do
   begin
      read(c);
      while (ord(c)<=32) and not(eof) do read(c);
      if ord(c)<=32 then break;
      repeat
         s:=s+c;
         if eof then break;
         read(c);
      until (ord(c)<=32);

      len:=length(s);
      if s='<br>' then begin writeln; i:=0; end
      else
      if s='<hr>' then
      begin
         if i>0 then writeln;
         for i:=1 to 80 do write('-');
         writeln;
         i:=0;
      end
      else
      begin
         if (i=0) then
         begin
            if len<80 then
            begin
               write(s);
               i:=len;
            end;
         end
         else
         begin
            if (i+1+len<=80) then
            begin
               write(' ',s);
               i:=i+1+len;
            end
            else
            begin
               writeln;
               write(s);
               i:=len;

            end;
         end;



      end;



      s:='';
   end;






end;
begin
{   assign(input,'p2271.in');
   assign(output,'p2271.out');
   reset(input);
   rewrite(output);
 }  cin;
   writeln;
  { close(input);
   close(output);}
end.

POJ 1700(过河问题)

玩过《雷顿》就知道这题可以贪心

小等于2人:1,2->

3人时:

1,3->

1<-

1,2->

1<-

否则:

1,2->

2<-

max1,max2->

1<-

OR

1,max1->

1<-

2,max2->

2<-

于是数据规模-2

Program P1700;
var
   t,n,i,j:longint;
   l,r:longint;
   a:array[1..1000] of longint;
procedure qsort(l,r:longint);
var
   i,j,m,p:longint;
begin
   i:=l;
   j:=r;
   m:=a[(l+r) shr 1];
   repeat
      while (a[i]<m) do inc(i);
      while (a[j]>m) do dec(j);
      if i<=j then
      begin
         p:=a[i];a[i]:=a[j];a[j]:=p;
         inc(i);
         dec(j);
      end;
   until i>j;
   if l<j then qsort(l,j);
   if i<r then qsort(i,r);

end;
function max(a,b:longint):longint;
begin
   if a<b then exit(b) else exit(a);
end;
function min(a,b:longint):longint;
begin
   if a>b then exit(b) else exit(a);
end;

function ww(x:longint):longint;
var
   i,j:longint;
begin
   if x=1 then exit(a[1]);
   if x=2 then exit(a[2]);
   if x=3 then exit(a[1]+a[2]+a[3]);
   i:=2*a[1]+a[x]+a[x-1];
   j:=2*a[2]+a[1]+a[x];
   exit(ww(x-2)+min(i,j));
                           //1,2-> 1< r1,r2-> 2<=
end;
begin
   read(t);
   while (t>0) do
   begin
      read(n);
      for i:=1 to n do read(a[i]);
      qsort(1,n);
      l:=1;r:=n;

      writeln(ww(n));

      dec(t);
   end;
end.

POJ 1125(Floyd)

裸Floyd

Program P1125;
const
   maxn=100;
   maxedge=10;
   NULL=-2139062144;
var
   n,i,j,k,m,v,t,ans:longint;
   f:array[1..maxn,1..maxn] of longint;
function max(a,b:longint):longint;
begin
   if a<b then exit(b) else exit(a);
end;
begin
   read(n);
   while (n<>0) do
   begin
      fillchar(f,sizeof(f),128);
      for i:=1 to n do
      begin
         f[i,i]:=0;
         read(m);
         for j:=1 to m do
         begin
            read(v,t);
            f[i,v]:=t;
         end;
      end;

      for k:=1 to n do
         for i:=1 to n do
            for j:=1 to n do
               if (f[i,k]<>NULL) and (f[k,j]<>NULL) then
                  if (f[i,k]+f[k,j]<f[i,j]) or (f[i,j]=NULL) then f[i,j]:=f[i,k]+f[k,j];
      ans:=maxlongint;

      v:=0;
      for i:=1 to n do
      begin
         t:=f[i,1];
         for j:=1 to n do
         begin
            if f[i,j]=NULL then break else t:=max(f[i,j],t);
         end;
         if f[i,j]=NULL then continue;
         if t<ans then begin v:=i; ans:=t; end;

      end;
      if (ans=maxlongint) then writeln('disjoint') else writeln(v,' ',ans);



      read(n);
   end;
end.

POJ 3842(质数判断)

7!=5040

所以这题直接求质数比打一千万的表都快

这提高诉我们阶乘其实不算大&看(算)清数据规模


Program cc;
var
   n,t,len,i,j,ans:longint;
   s:string;
   b:array[0..9] of longint;
procedure dfs(p,l:longint);
var
   i:longint;
begin
   if l=len then
   begin
      if p=1 then exit;
      for i:=2 to trunc(sqrt(p)) do if (p mod i=0) then exit;
      inc(ans);
      exit;
   end;
   for i:=0 to 9 do
   if b[i]>0 then
   begin
      if (i=0) and (l=0) then continue;
      dec(b[i]);
      dfs(p*10+i,l+1);
      inc(b[i]);
   end;

end;
begin
   readln(t);
   while (t>0) do
   begin
      readln(s);
      len:=length(s);
      fillchar(b,sizeof(b),0);
      for i:=1 to len do inc(b[ord(s[i])-48]);
      ans:=0;
      for i:=1 to len do
      begin
         dfs(0,0);
         dec(len);
      end;
      writeln(ans);


      dec(t);
   end;
end.

CF 187A(从后取数的重排数列)

题目大意:一串数,每次把最后那个数挪到前面任意位置,就最少挪动次数

显然一个数最多挪一次(只能从后取的话,插2次的一定能变成1次)

因此找最后挪动的数即可,最后挪动的数即由于与下序列的连线与之前的交叉,其它数无论怎么挪都无法影响到它)

Program DD;
const
   maxn=200000;
var
   n,i,j,l,r:longint;
   a,b,hposa,hposb:array[1..maxn] of longint;
begin
   read(n);
   for i:=1 to n do
   begin
      read(a[i]);
      hposa[a[i]]:=i;
   end;
   for i:=1 to n do
   begin
      read(b[i]);
      hposb[b[i]]:=i;
   end;
   r:=0;
   for i:=1 to n do
   begin
       if r<hposb[a[i]] then r:=hposb[a[i]]
       else break;
   end;
   if (r=hposb[a[i]]) then writeln('0') else
   writeln(n-i+1);

end.

POJ 2588(解析几何+并查集)

题目就是早从左到右的路

注意输入的实数

这题图画好就行,别像我一开始把图弄反就成

从上开始找,若找到一个与下边界相邻的就无解,找到与左边相邻的记圆与左边界相交的下边的点(相当于左上角挖去一块),右边同理。

Program snake;
const
   maxn=1000;
var
   n,i,j:longint;
   x,y,r,lc,rc:array[1..maxn] of double;
   maxl,maxr:double;
   father:array[1..maxn] of longint;
   b,up,down,left,right:array[1..maxn] of boolean;
function getfather(x:longint):longint;
begin
   if father[x]=x then exit(x);
   father[x]:=getfather(father[x]);
   exit(father[x]);
end;
Procedure union(x,y:longint);
begin
   father[father[x]]:=father[father[y]];
end;
function distance(i,j:longint):double;
begin
   exit(sqrt(sqr(x[i]-x[j])+sqr(y[i]-y[j])));
end;
function dis(x1,y1,x2,y2:double):double;
begin
   exit(sqrt(sqr(x1-x2)+sqr(y1-y2)));
end;

begin
   fillchar(b,sizeof(b),false);
   fillchar(up,sizeof(up),false);
   fillchar(down,sizeof(down),false);
   fillchar(left,sizeof(left),false);
   fillchar(right,sizeof(right),false);
   fillchar(lc,sizeof(lc),0);
   fillchar(rc,sizeof(rc),0);
   maxl:=1000;maxr:=1000;

   read(n);
   for i:=1 to n do
   begin
      read(x[i],y[i],r[i]);
      father[i]:=i;
      for j:=1 to i-1 do
         if distance(i,j)<r[i]+r[j] then
            if getfather(i)<>getfather(j) then
               union(i,j);
      if (y[i]<r[i]) then down[i]:=true;
      if (y[i]+r[i]>1000) then up[i]:=true;
      if (x[i]<r[i]) then
      begin
         left[i]:=true;
         lc[i]:=y[i]-sqrt(sqr(r[i])-sqr(x[i]));
      end;
      if (x[i]+r[i]>1000) then
      begin
         right[i]:=true;
         rc[i]:=y[i]-sqrt(sqr(r[i])-sqr(1000-x[i]));
      end;

   end;
   for i:=1 to n do
      if (up[i]) and not(b[i]) then
      begin
         for j:=1 to n do
            if father[i]=father[j] then
            begin
               b[j]:=true;
               if (down[j]) then
               begin
                  writeln('Bill will be bitten.');
                  halt;
               end;
               if left[j] then
               begin
                  if lc[j]<maxl then maxl:=lc[j];

               end;
               if right[j] then
               begin
                  if rc[j]<maxr then maxr:=rc[j];
               end;


            end;
      end;
   writeln('Bill enters at (0.00, ',maxl:2:2,') and leaves at (1000.00, ',maxr:2:2,').');




end.

POJ 3122(二分答案)

二分答案……

Program pie;
const
   lef=0.00001;
var
   t,n,f,i,j:longint;
   r:array[1..10000] of longint;
   s:array[1..10000] of double;
   maxs:double;
procedure sort(l,r:double);
var
   m:real;
   i,j,tot:longint;
begin
   m:=(l+r)/2;
   tot:=0;
   for i:=1 to n do inc(tot,trunc(s[i]/m));

   if tot>=f then
   begin
      if r-l<lef then writeln(r:4:4)
      else sort(m,r);


   end
   else sort(l,m);










end;
begin
   read(t);
   while (t>0) do
   begin
      read(n,f);
      inc(f);
      for i:=1 to n do
      begin
         read(r[i]);
         s[i]:=sqr(r[i])*pi;
      end;
      maxs:=s[1];
      for i:=2 to n do
         if maxs<s[i] then maxs:=s[i];
      sort(0,maxs);

      dec(t);
   end;
end.

POJ 3844(同余)

果断同余……

D[j]-D[i]  mod  k =0

D[j]=D[i]

求有多少相等数对,用队列O(n)

Program P3844;
const
   maxn=50000;
   maxd=1000000;
var
   ans,t,f,n,i,j:longint;
   d:array[0..maxn] of longint;
procedure qsort(l,r:longint);
var
   i,j,m,p:longint;
begin
   i:=l;j:=r;
   m:=d[(l+r) shr 1];
   repeat
      while d[i]<m do inc(i);
      while d[j]>m do dec(j);
      if i<=j then
      begin
         p:=d[i];
         d[i]:=d[j];
         d[j]:=p;
         inc(i);dec(j);
      end;

   until i>j;
   if l<j then qsort(l,j);
   if i<r then qsort(i,r);

end;
begin
   read(t);
   d[0]:=0;
   while (t>0) do
   begin
      read(f,n);
      for i:=1 to n do
      begin
         read(d[i]);
         d[i]:=(d[i]+d[i-1]) mod f;
      end;
      qsort(1,n);

      ans:=0;
      i:=0;j:=0;
      while (i<=n) do
      begin
         while (d[i]=d[j]) and (j<n) do inc(j);
         if d[i]<>d[j] then dec(j);
         inc(ans,((j-i+1)*(j-i)) shr 1);
         i:=j+1;
         inc(j);
      end;


      writeln(ans);

      dec(t);
   end;
end.

POJ 2184(01背包+滚动数组)

01背包 模板题

Program dd;
const
   maxn=1000;
   maxv=100000;
   minv=-100000;
   NULL=-2139062144;
var
   n,i,j,ans,p,np:longint;
   ts,tf:array[1..maxn] of longint;
   f:array[0..1,minv..maxv] of longint;
function max(a,b:longint):longint;
begin
   if a<b then exit(b) else exit(a);
end;
begin
   read(n);
   for i:=1 to n do read(ts[i],tf[i]);
   fillchar(f,sizeof(f),128);
   f[0,0]:=0;
   for i:=1 to n do
   begin
      p:=i mod 2;
      fillchar(f[p],sizeof(f[p]),128);
      np:=(p+1) mod 2;

      for j:=maxv downto minv do
      begin
         f[p,j]:=f[np,j];
         if (minv<=j-ts[i]) and (j-ts[i]<=maxv) then
            if (f[np,j-ts[i]]<>NULL) then
               f[p,j]:=max(f[p,j],f[np,j-ts[i]]+tf[i]);



      end;
   end;


   ans:=0;
   for i:=0 to maxv do
      if (f[n mod 2,i]>=0) and (ans<f[n mod 2,i]+i) then ans:=f[n mod 2,i]+i;

   writeln(ans);

end.