海清's profileCockhorse BlogPhotosBlogListsMore Tools Help

Blog


    February 29

    边数最少的最小割

    var crest,c,cbak:array[1..32,1..32]of longint;
        a:array[1..32,0..32]of longint;
        ans,l1,l2,l3,cut:array[1..1000]of longint;
        p,q:array[1..32]of longint;
        flow,min,p1,p2,m,n,dep,cn,maxf,sum:longint;   procedure init;
    var i,j:longint;
    begin
     read(n,m);
     for i:=1 to m do
      begin
       read(l1[i],l2[i],l3[i]);
       inc(c[l1[i],l2[i]],l3[i]);
      end;
     for i:=1 to n do
      for j:=1 to n do
       if c[i,j]>0 then begin
                         inc(a[i,0]);
                         a[i,a[i,0]]:=j;
                         inc(a[j,0]);
                         a[j,a[j,0]]:=i;
                        end;
     cbak:=c;
    end;   function find:boolean;
    var j:longint;
    begin
     fillchar(p,sizeof(p),255);
     p1:=1;p2:=1;
     q[1]:=1; p[1]:=0;
     repeat
      for j:=1 to a[q[p1],0] do
       if (p[a[q[p1],j]]<0)and(c[q[p1],a[q[p1],j]]>0)
         then begin
                inc(p2);
                q[p2]:=a[q[p1],j];
                p[q[p2]]:=q[p1];
                if q[p2]=n then exit(true);
              end;
      inc(p1);
     until p1>p2;
     exit(false);
    end;   function maxflow:longint;
    var s,i:longint;
    begin
     s:=0;
     while true do
      if find then begin
                    min:=999999999;i:=n;
                    while p[i]<>0 do
                     begin
                      if min>c[p[i],i] then min:=c[p[i],i];
                      i:=p[i];
                     end;
                    s:=s+min;
                    i:=n;
                    while p[i]<>0 do
                     begin
                      dec(c[p[i],i],min);
                      inc(c[i,p[i]],min);
                      i:=p[i];
                     end;
                   end
             else break;
     exit(s);
    end;   procedure mincut;
    var i:longint;
    begin
     sum:=0;
     crest:=c;
     for i:=1 to m do
      if crest[l1[i],l2[i]]=0 then
      begin
       c:=cbak;
       dec(c[l1[i],l2[i]],l3[i]);
       if flow-maxflow=l3[i] then begin
                                    inc(cn);
                                    cut[cn]:=i;
                                    inc(sum,l3[i]);
                                  end;
      end;
    end;   procedure out;
    var i:longint;
    begin
     writeln(flow,' ',dep);
     for i:=1 to dep do
      writeln(ans[i]);
     halt;
    end;   procedure dfs(i,last,s:longint);
    var j:longint;
    begin
     if i>dep then begin
                    if s=flow then out;
                    exit;
                   end;
     for j:=last+1 to cn do
      begin
       ans[i]:=j;
       dfs(i+1,j,s+l3[j]);
      end;
    end;   begin
     init;
     flow:=maxflow;
     mincut;
     if sum=flow then begin
                        ans:=cut;
                        dep:=cn;
                        out;
                      end;
     for dep:=1 to cn do
      dfs(1,0,0);
    end.

    字典序最小的欧拉回路或欧拉路

    以最小的点开始,从小到大搜存在一个数组里,最后倒起输出来即可
    var
      n,i,j,s,t,m:word;
      con:array[1..500,1..500]of word;
      d:array[1..500]of word;
      cir:boolean;
      path:array[1..1025]of word;
    procedure search (s:word);
    var
      i:word;
    begin
      for i:=1 to m do
        if con[s,i]>0 then
        begin
          dec(con[s,i]);
          dec(con[i,s]);
          search(i);
        end;
      inc(j);
      path[j]:=s;
    end;
    begin
      readln(n);
      for i:=1 to n do
      begin
        readln(s,t);
        inc(con[s,t]);
        inc(con[t,s]);
        inc(d[s]);
        inc(d[t]);
        if s>m then
          m:=s;
        if t>m then
          m:=t;
      end;
      cir:=true;
      for i:=1 to m do
        if odd(d[i]) then
        begin
          s:=i;
          cir:=false;
          break;
        end;
      j:=0;
      if cir then
        search(1)
      else
        search(s);
      for i:=n+1 downto 1 do
        writeln(path[i]);
    end.
    February 27

    树的划分 一道多叉转二叉的树规

    type
      ss=record
        left,right:longint;
      end;
    var
      a:array[1..100]of ss;
      f:array[1..100,0..100]of longint;
      d,b,v,g:array[1..100]of longint;
      i,j,k,l,n,m,o,ans:longint;
      h:array[1..100]of boolean;
    function min(a,b:longint):longint;
    begin
      if a<b then exit(a) else exit(b);
    end;
    procedure bfs;
    var
      now,l,r,k:longint;
    begin
      b[1]:=i;l:=0;r:=1;
      d[1]:=i;k:=1;
      repeat
        inc(l);
        now:=b[l];
        if a[now].left<>0 then
        begin
          inc(k);
          d[k]:=a[now].left;
          inc(r);b[r]:=a[now].left;
        end;
        if a[now].right<>0 then
        begin
          inc(k);
          d[k]:=a[now].right;
          inc(r);b[r]:=a[now].right;
        end;
      until l=r;
    end;
    begin
      readln(n,m);
      if m=1 then
      begin
        writeln(1);halt;
      end;
      for i:=1 to n-1 do
      begin
        readln(j,k);
        if v[j]=0 then
          a[j].left:=k
        else a[v[j]].right:=k;
        v[j]:=k;
        h[k]:=true;
      end;
      for i:=1 to n do
      if not h[i] then
        break;
      bfs;
      for i:=1 to n do
      for j:=0 to m do
        f[i,j]:=maxint;
      for l:=n downto 1 do
      begin
        i:=d[l];
        g[i]:=1;
        if a[i].right<>0 then
        begin
          inc(g[i],g[a[i].right]);
          f[i,0]:=f[a[i].right,0]+1;
        end
        else f[i,0]:=1;
        if a[i].left<>0 then inc(g[i],g[a[i].left]);
        for j:=1 to m do
        if j>g[i] then break
        else
        begin
          if a[i].right<>0 then
          begin
            f[i,j]:=min(f[i,j],f[a[i].right,j]+1);
            if a[i].left=0 then
            begin
              f[i,j]:=min(f[i,j],f[a[i].right,j-1]);
              continue;
            end
            else f[i,j]:=min(f[i,j],f[a[i].right,j-1]+1)
          end
          else
          begin
            if a[i].left<>0 then
              f[i,j]:=f[a[i].left,j-1]
            else f[i,j]:=0;
            continue;
          end;
          for k:=1 to j-1 do
          if k>g[a[i].left] then break
          else f[i,j]:=min(f[i,j],f[a[i].left,k]+f[a[i].right,j-k-1]);
        end;
      end;
      ans:=maxlongint;
      for i:=1 to n do
      if d[1]<>i then
        if a[i].left<>0 then
          ans:=min(ans,f[a[i].left,m-1]+1)
        else
      else ans:=min(ans,f[a[i].left,m-1]);
      writeln(ans);
    end.

    中国剩余定理 O(nlogn)

    因为gcd的复杂度是logn(底数不为2,跟Fibonacci数列通项有关,约等于1.618)

    var
      m,a:array[1..100000]of longint;
      i,n,d,ans,x,y,o:longint;
    function gcd(a,b:longint;var x,y:longint):longint;
    var
      t:longint;
    begin
      if b=0 then
      begin
        x:=1;y:=0;
        exit(a);
      end;
      gcd:=gcd(b,a mod b,x,y);
      t:=x;
      x:=y;
      y:=t-a div b*y;
    end;
    begin
      readln(n);
      o:=1;
      for i:=1 to n do
      begin
        readln(m[i],a[i]);
        o:=o*m[i];
      end;
      for i:=1 to n do
      begin
        d:=gcd(o div m[i],m[i],x,y);
        m[i]:=m[i] div d;    {不互质时改值}
        o:=o div d;
        a[i]:=a[i] mod m[i];
        d:=gcd(o div m[i],m[i],x,y);
        x:=(x mod m[i]+m[i])mod m[i];{保证x为正数}
        inc(ans,o div m[i]*x*a[i]);
      end;
      writeln(ans mod o);
    end.

    用spfa判负环 O(mn)

    实践证明比bellman-ford判负环快

    type
      link=^rec;
      rec=record
        e,i:longint;
        point:link;
      end;
    function spfa:boolean;{n个点 m条边}
    var
      now,l,r,i:longint;
      b,f:array[1..1000]of longint;
      h:array[1..1000]of boolean;
      p:link;
    begin
      for i:=1 to n do f[i]:=maxlongint;
      f[1]:=0;
      fillchar(d,sizeof(d),0);
      fillchar(h,sizeof(h),0);
      l:=0;r:=1;
      h[1]:=true;b[1]:=i;
      repeat
        inc(l);if l>1000 then l:=1;{循环队列}
        now:=b[l];
        p:=v[now];
        while p<>nil do
        begin
          if f[now]+p^.e<f[p^.i] then
          begin
            inc(d[now]);if d[now]>m then exit(true);{某个点用的次数超过边数则肯定存在负环}
            f[p^.i]:=f[now]+p^.e;
            if not h[p^.i] then
            begin
              inc(r);if r>1000 then r:=1;
              b[r]:=p^.i;
            end;
          end;
          p:=p^.point;
        end;
        h[now]:=false;
      until l=r;
      exit(false);
    end;

    多重背包

    1.把个数表示成若干个2^k次方形式,再用01背包做  O(nvlogv)

    var
        v,i,j,k,l,n,max,o,d:longint;
        f,a,w:array[0..10000]of longint;
    begin
        readln(n,v);
        for i:=1 to n do
        begin
            readln(j,k,d);
            o:=1;
            while d-o shl 1+1>=0 do
            begin
                inc(l);a[l]:=o*j;w[l]:=o*k;
                o:=o shl 1;
            end;
            o:=d-o+1;
            inc(l);a[l]:=o*j;w[l]:=o*k;
        end;
        for i:=1 to l do
          for j:=v downto a[i] do
            if f[j-a[i]]+w[i]>f[j] then
               f[j]:=f[j-a[i]]+w[i];
        for i:=1 to v do
          if f[i]>max then max:=f[i];
        writeln(max);
    end.

    2.队列优化 O(nv)

    var
      l,r,f,a,w,d:array[0..10000]of longint;
      b:array[0..1000,1..10000]of longint;
      v,i,j,k,n,t:longint;
    function max(a,b:longint):longint;
    begin
      if a<b then exit(b) else exit(a);
    end;
    begin
      readln(n,v);
      for i:=1 to n do readln(a[i],w[i],d[i]);
      for i:=1 to n do
      begin
        fillchar(b,sizeof(b),0);
        if a[i]>v then continue;
        for j:=v downto v-a[i]+1 do
        begin
          t:=j mod a[i];
          r[t]:=0;
          for k:=1 to d[i] do
          if j-k*a[i]<0  then break
          else
          begin
            while (r[t]>0)and(f[j-k*a[i]]+k*w[i]>f[b[t,r[t]]]+w[i]*(j-b[t,r[t]])div a[i]) do
              dec(r[t]);
            inc(r[t]);
            b[t,r[t]]:=j-k*a[i];
          end;
          if r[t]>0 then
          begin
            f[j]:=max(f[j],f[b[t,1]]+w[i]*(j-b[t,1])div a[i]);
            if b[t,1]=j-a[i] then l[t]:=2
            else l[t]:=1;
          end
          else l[t]:=1;
        end;
        for j:=v-a[i] downto a[i] do
        begin
          t:=j mod a[i];
          while (r[t]>=l[t])and(j-d[i]*a[i]>=0)and
          (f[j-d[i]*a[i]]+d[i]*w[i]>f[b[t,r[t]]]+w[i]*(j-b[t,r[t]])div a[i]) do
            dec(r[t]);
          if j-d[i]*a[i]>=0 then
          begin
            inc(r[t]);
            b[t,r[t]]:=j-d[i]*a[i];
          end;
          if r[t]>=l[t] then
            f[j]:=max(f[j],f[b[t,l[t]]]+w[i]*(j-b[t,l[t]])div a[i]);
          if b[t,l[t]]=j-a[i] then inc(l[t]);
        end;
      end;
      for i:=1 to v do f[i]:=max(f[i-1],f[i]);
      writeln(f[v]);
    end.

    February 25

    用左偏树写的排序

    type
      heap=^rec;
      rec=record
        left,right:heap;
        x,d:longint;
      end;
    var
      p,h:heap;
      i,k,n:longint;
    function merge(var a,b:heap):heap;
    var
      c:heap;
    begin
      if a=nil then exit(b);
      if b=nil then exit(a);
      if a^.x>b^.x then
      begin
        c:=a;a:=b;b:=c;
      end;
      a^.right:=merge(a^.right,b);
      if (a^.left=nil)or(a^.left^.d<=a^.right^.d) then
      begin
        c:=a^.left;a^.left:=a^.right;a^.right:=c;
      end;
      if a^.right=nil then a^.d:=0
      else a^.d:=a^.right^.d+1;
      exit(a);
    end;
    begin
      readln(n);
      for i:=1 to n do
      begin
        read(k);
        new(p);
        p^.x:=k;p^.left:=nil;p^.right:=nil;p^.d:=0;
        h:=merge(p,h);
      end;
      for i:=1 to n do
      begin
        writeln(h^.x);
        h:=merge(h^.left,h^.right);
      end;
    end.

    treap 更新版

    还是觉得递归+函数返回的形式比较科学

    type
      tree=^rec;
      rec=record
        left,right:tree;
        ld,rd,x:longint;
        e:double;
      end;
    function left(var p:tree):tree;{左旋}
    var
      t:tree;
    begin
      t:=p^.left;p^.left:=t^.right;t^.right:=p;
      dec(p^.ld,t^.ld+1);
      inc(t^.rd,p^.rd+1);
      exit(t);
    end;

    function right(var p:tree):tree;{右旋}
    var
      t:tree;
    begin
      t:=p^.right;p^.right:=t^.left;t^.left:=p;
      dec(p^.rd,t^.rd+1);
      inc(t^.ld,p^.ld+1);
      exit(t);
    end;

    function insert(x:longint;var p:tree):tree;{插入x元素}
    begin
      if p=nil then
      begin
        writeln(o+1);{输出它是第几大}
        new(p);
        p^.left:=nil;p^.right:=nil;
        p^.x:=x;p^.ld:=0;p^.rd:=0;p^.e:=random;
        exit(p);
      end;
      if x<p^.x then
      begin
        inc(o,p^.rd+1);{o记录比x大的有多少}
        p^.left:=insert(x,p^.left);
        inc(p^.ld);
        if p^.left^.e<p^.e then
          p:=left(p);
        exit(p);
      end
      else
      begin
        p^.right:=insert(x,p^.right);
        inc(p^.rd);
        if p^.right^.e<p^.e then
          p:=right(p);
        exit(p);
      end;
    end;

    function delete(var p:tree):tree;{删除p节点}
    begin
      if (p^.left=nil)and(p^.right=nil) then
      begin
        dispose(p);
        exit(nil);
      end;
      if (p^.left<>nil)and((p^.right=nil)or(p^.left^.e<p^.right^.e)) then
      begin
        p:=left(p);
        p^.right:=delete(p^.right);
        dec(p^.rd);
        exit(p);
      end
      else
      begin
        p:=right(p);
        p^.left:=delete(p^.left);
        dec(p^.ld);
        exit(p);
      end;
    end;

    function find(x:longint;var p:tree):tree; {查找第x大元素}
    begin
      if o+p^.rd+1=x then{o记录该节点的上面有多少比它大,初始值为0}
      begin
        writeln(p^.x);{输出这个数并删除}
        p:=delete(p);{如果需要删除}
        exit(p);
      end;
      if x<o+p^.rd+1 then
      begin
        p^.right:=find(x,p^.right);
        dec(p^.rd);{只是查找就不变}
        exit(p);
      end
      else
      begin
        inc(o,p^.rd+1);
        p^.left:=find(x,p^.left);
        dec(p^.ld);
        exit(p);
      end;
    end;

    次小生成树 更新版

    type
      link=^rec;
      rec=record
        i,e:longint;
        point:link;
      end;
    var
      v:array[1..1000]of link;
      p:link;
      f:array[1..1000]of boolean;
      a,g:array[1..1000,1..1000]of longint;
      t:array[1..1000,1..1000]of boolean;
      d,b:array[1..1000]of longint;
      ans,i,j,k,l,n,m,o:longint;
    procedure dfs(i,j,o:longint);
    var
      p:link;
    begin
      a[i,j]:=o;
      f[j]:=true;
      p:=v[j];
      while p<>nil do
      begin
        if not f[p^.i] then
          if p^.e>o then
            dfs(i,p^.i,p^.e)
          else dfs(i,p^.i,o);
        p:=p^.point;
      end;
    end;
    begin
      readln(n,m);
      for i:=1 to n do
      for j:=1 to n do
        g[i,j]:=maxlongint;
      for i:=1 to n do d[i]:=maxlongint;
      for i:=1 to m do
      begin
        readln(j,k,l);
        g[j,k]:=l;g[k,j]:=l;
        if k=1 then
        begin
          b[j]:=1;d[j]:=l;
        end;
        if j=1 then
        begin
          b[k]:=1;d[k]:=l;
        end;
      end;
      f[1]:=true;
      for i:=1 to n-1 do
      begin
        k:=0;o:=maxlongint;
        for j:=2 to n do
        if (not f[j])and(d[j]<o) then
        begin
          o:=d[j];k:=j;
        end;
        f[k]:=true;inc(ans,o);
        for j:=2 to n do
        if (not f[j])and(g[k,j]<d[j]) then
        begin
          d[j]:=g[k,j];b[j]:=k;
        end;
      end;
      for i:=2 to n do
      begin
        t[i,b[i]]:=true;t[b[i],i]:=true;
        new(p);
        p^.i:=b[i];p^.e:=g[i,b[i]];
        p^.point:=v[i];v[i]:=p;
        new(p);
        p^.i:=i;p^.e:=g[i,b[i]];
        p^.point:=v[b[i]];v[b[i]]:=p;
      end;
      for i:=1 to n do
      begin
        fillchar(f,sizeof(f),0);
        dfs(i,i,0);
      end;
      o:=maxlongint;
      for i:=1 to n-1 do
      for j:=i+1 to n do
      if (not t[i,j])and(g[i,j]-a[i,j]<o) then
        o:=g[i,j]-a[i,j];
      writeln(ans+o);
    end.

    高精加减乘除

    type
      ss=array[0..100]of byte;
    function bigger(a,b:ss):boolean;
    var
      i:longint;
    begin
      if a[0]<>b[0] then
        if a[0]<b[0] then
          exit(false)
        else exit(true);
      for i:=a[0] downto 1 do
      if a[i]<>b[i] then
        if a[i]<b[i] then
          exit(false)
        else exit(true);
      exit(true);
    end;

    function jia(a,b:ss):ss;
    var
      i,o,k,l:longint;
    begin
      l:=max(a[0],b[0])+1;
      k:=0;
      for i:=1 to l do
      begin
        o:=a[i]+b[i]+k;
        a[i]:=o mod 10;
        k:=o div 10;
      end;
      while (a[a[0]]=0)and(a[0]>1) do dec(a[0]);
      exit(a);
    end;

    function jian(a,b:ss):ss;
    var
      i,o,k:longint;
    begin
      k:=0;
      for i:=1 to a[0] do
      begin
        o:=a[i]+10-b[i]-k;
        a[i]:=o mod 10;
        k:=1-o div 10;
      end;
      while (a[a[0]]=0)and(a[0]>1) do dec(a[0]);
      exit(a);
    end;

    function cheng(a:ss;x:longint):ss;
    var
      i,o,k:longint;
    begin
      inc(a[0],trunc(ln(x)/ln(10))+1);
      k:=0;
      for i:=1 to a[0] do
      begin
        o:=a[i]*x+k;
        a[i]:=o mod 10;
        k:=o div 10;
      end;
      while (a[a[0]]=0)and(a[0]>1) do dec(a[0]);
      exit(a);
    end;

    function cheng2(a,b:ss):ss;
    var
      i,j,o,k:longint;
      c:ss;
    begin
      c[0]:=a[0]+b[0]+1;
      for i:=1 to a[0]+1 do
      begin
        k:=0;
        for j:=1 to b[0]+1 do
        begin
          o:=a[i]*b[j]+c[i+j-1]+k;
          c[i+j-1]:=o mod 10;
          k:=o div 10;
        end;
      end;
      while (c[c[0]]=0)and(c[0]>1) do dec(c[0]);
      exit(c);
    end;

    function chu(a:ss;x:longint;var rest:longint):ss;
    var
      i,o:longint;
    begin
      rest:=0;
      for i:=a[0] downto 1 do
      begin
        o:=rest*10+a[i];
        rest:=o mod x;
        a[i]:=o div x;
      end;
      while (a[a[0]]=0)and(a[0]>1) do dec(a[0]);
      exit(a); 
    end;

    function chu2(a,b:ss;var ans,rest:ss):ss;
    var
      l,i:longint;
    begin
      fillchar(rest,sizeof(rest),0);
      rest[0]:=1;
      for i:=a[0] downto 1 do
      begin
        rest:=cheng(rest,10);
        rest[1]:=a[i];l:=0;
        while bigger(rest,b) do
        begin
          rest:=jian(rest,b);
          inc(l);
        end;
        a[i]:=l;
      end;
      while (a[a[0]]=0)and(a[0]>1) do dec(a[0]);
      exit(a);
    end;

    金明的预算 依赖背包写法

    var
      a,w:array[1..60,0..10]of longint;
      f:array[0..200000]of longint;
      i,j,k,l,n,o,v:longint;
    function max(a,b:longint):longint;
    begin
      if a>b then exit(a) else exit(b);
    end;
    begin
      readln(v,n);
      for i:=1 to n do
      begin
        readln(j,k,l);
        if l=0 then l:=i;
        inc(a[l,0]);
        a[l,a[l,0]]:=j;w[l,a[l,0]]:=j*k;
      end;
      for i:=1 to n do
      if a[i,0]>0 then
      begin
        fillchar(f,sizeof(f),0);
        for j:=2 to a[i,0] do
        for k:=v-a[i,1] downto a[i,j] do
        if (f[k-a[i,j]]>0)or(k=a[i,j]) then
          f[k]:=max(f[k],f[k-a[i,j]]+w[i,j]);
        l:=0;k:=a[i,1];o:=w[i,1];
        for j:=0 to v-k do
        if (f[j]<>0)or(j=0) then
        begin
          inc(l);
          a[i,l]:=k+j;w[i,l]:=f[j]+o;
        end;
        a[i,0]:=l;
      end;
      fillchar(f,sizeof(f),0);
      for i:=1 to n do
      for k:=v downto 0 do
      for j:=1 to a[i,0] do
      if k>=a[i,j] then
        f[k]:=max(f[k],f[k-a[i,j]]+w[i,j]);
      for i:=1 to v do f[i]:=max(f[i-1],f[i]);
      writeln(f[v]);
    end.

    February 05

    凸包(cos排序)

    type
      ss=record
        x,y,c:double;
      end;
    var
      a,b:array[1..100000]of ss;
      i,j,n:longint;
      d:ss;
      o:double;
    procedure qsort(l,r:longint);
    var
      i,j:longint;
      mid,midx:double;
      k:ss;
    begin
      i:=l;j:=r;mid:=a[(l+r)shr 1].c;midx:=a[(l+r)shr 1].x;
      repeat
        while (a[i].c<mid)or((a[i].c=mid)and(abs(a[i].x-d.x)<abs(midx-d.x))) do inc(i);
        while (a[j].c>mid)or((a[j].c=mid)and(abs(a[j].x-d.x)>abs(midx-d.x))) do dec(j);
        if i<=j then
        begin
          k:=a[i];a[i]:=a[j];a[j]:=k;
          inc(i);dec(j);
        end;
      until i>j;
      if j>l then qsort(l,j);
      if i<r then qsort(i,r);
    end;
    begin
      readln(n);
      d.y:=maxlongint;
      for i:=1 to n do
      begin
        readln(a[i].x,a[i].y);
        if (a[i].y<d.y)or((a[i].y=d.y)and(a[i].x<d.x)) then
          d:=a[i];
      end;
      for i:=1 to n do
        if (d.x<>a[i].x)or(d.y<>a[i].y) then
          a[i].c:=(d.x-a[i].x)/sqrt(sqr(a[i].x-d.x)+sqr(a[i].y-d.y))
        else a[i].c:=-1;
      qsort(1,n);
      b[1]:=a[1];b[2]:=a[2];a[n+1]:=a[1];j:=2;
      for i:=3 to n+1 do
      begin
        while (b[j].x-b[j-1].x)*(a[i].y-b[j-1].y)<(a[i].x-b[j-1].x)*(b[j].y-b[j-1].y) do
          dec(j);
        inc(j);b[j]:=a[i];
      end;
      for i:=1 to j-1 do writeln(b[i].x:0:2,' ',b[i].y:0:2);
    end.

    fence4(计算几何经典题目)

    {
    ID:whqlsc1
    LANG:PASCAL
    TASK:fence4
    }
    type
      ss=record
        c,x,y:double;
      end;
    var
      a,b:array[1..200]of ss;
      f:array[1..200]of boolean;
      i,j,k,l,n,m,o:longint;
      e:double;
      p,d,c:ss;
    function chaji(a,b,c,d:ss):double;
    var
      x1,x2,y1,y2:double;
    begin
      x1:=b.x-a.x;y1:=b.y-a.y;
      x2:=d.x-c.x;y2:=d.y-c.y;
      exit(x1*y2-x2*y1);
    end;
    function xiangjiao(a,b,c,d:ss):boolean;
    begin
      if (chaji(a,c,a,b)*chaji(a,d,a,b)<0)and(chaji(c,a,c,d)*chaji(c,b,c,d)<0) then
        exit(true)
      else exit(false);
    end;
    function xiangjiao2(a,b,c,d:ss;var p:ss):boolean;
    var
      s1,s2,s3:double;
    begin
      s1:=chaji(a,b,a,c);
      s2:=chaji(a,b,a,d);
      s3:=chaji(a,c,a,d);
      if (s1*s2>=0)or(s1*s3>=0) then exit(false);
      p.x:=(s2*c.x-s1*d.x)/(s2-s1);
      p.y:=(s2*c.y-s1*d.y)/(s2-s1);
      exit(true);
    end;
    begin
      assign(input,'fence4.in');
      assign(output,'fence4.out');
      reset(input);
      rewrite(output);
      readln(n);
      readln(d.x,d.y);
      for i:=1 to n do
      begin
        readln(a[i].x,a[i].y);
        if a[i].y>=d.y then
          k:=1
        else k:=-1;
        if (a[i].x<>d.x)or(a[i].y<>d.y) then
          a[i].c:=((a[i].x-d.x)/sqrt(sqr(a[i].x-d.x)+sqr(a[i].y-d.y))+1)*k
        else a[i].c:=2;
      end;
      a[n+1]:=a[1];
      for i:=1 to n-2 do
      for j:=i+2 to n do
      if xiangjiao(a[i],a[i+1],a[j],a[j+1]) then
      begin
        writeln('NOFENCE');
        close(output);halt;
      end;
      b:=a;
      for i:=1 to n do
      for j:=1 to n-1 do
      if b[j].c<b[j+1].c then
      begin
        c:=b[j];b[j]:=b[j+1];b[j+1]:=c;
      end;
      b[n+1]:=b[1];o:=0;
      for i:=1 to n do
      if chaji(d,b[i],d,b[i+1])>0 then
      begin
        c.x:=(b[i].x+b[i+1].x)/2;
        c.y:=(b[i].y+b[i+1].y)/2;
        e:=0;k:=0;
        for j:=1 to n do
        if xiangjiao2(d,c,a[j],a[j+1],p) then
          if (k=0)or(abs(p.x-d.x)+abs(p.y-d.y)<e) then
          begin
            k:=j;e:=abs(p.x-d.x)+abs(p.y-d.y);
          end;
        if k<>0 then
        begin
          if not f[k] then inc(o);
          f[k]:=true;
        end;
      end;
      writeln(o);
      for i:=1 to n-2 do
      if f[i] then
        writeln(a[i].x:0:0,' ',a[i].y:0:0,' ',a[i+1].x:0:0,' ',a[i+1].y:0:0);
      if f[n] then
        writeln(a[1].x:0:0,' ',a[1].y:0:0,' ',a[n].x:0:0,' ',a[n].y:0:0);
      if f[n-1] then
        writeln(a[n-1].x:0:0,' ',a[n-1].y:0:0,' ',a[n].x:0:0,' ',a[n].y:0:0);
      close(output);
    end.

    判断点在多边形内外

    uses math;
    type
        ss=record
            x,y:longint;
        end;
    var
        a:array[1..10000]of ss;
        k,x,y,i,n:longint;
        o:double;
    begin
        readln(n,x,y);
        for i:=1 to n do readln(a[i].x,a[i].y);
        a[n+1]:=a[1];
        for i:=1 to n do
        begin
            if (a[i].x-x)*(a[i+1].y-y)-(a[i+1].x-x)*(a[i].y-y)<0 then
                k:=-1
            else k:=1;
            o:=o+k*arccos(((a[i].x-x)*(a[i+1].x-x)+(a[i].y-y)*(a[i+1].y-y))/
            sqrt(sqr(a[i].x-x)+sqr(a[i].y-y))/sqrt(sqr(a[i+1].x-x)+sqr(a[i+1].y-y)));
        end;
        if abs(o)>1.57 then writeln(true)
        else writeln(false);
    end.

    半平面相交

    type
        ss=record
            x,y,c:double;
        end;
        ss2=record
            a,b,c:longint;
            x1,y1,x2,y2:double;
        end;
    var
        a,b:array[1..1000]of ss;
        f:array[1..1000]of ss2;
        i,j,k,l,n,m:longint;
        x,y,s1,s2,o:double;
        d:ss;
        u:boolean;
    begin
        randomize;
        readln(n);
        for i:=1 to n do
        begin
            readln(f[i].a,f[i].b,f[i].c);
            if f[i].a=0 then
            begin
                f[i].x1:=random(100)+1;f[i].y1:=f[i].c/f[i].b;
            end
            else
            begin
                f[i].x1:=f[i].c/f[i].a;f[i].y1:=0;
            end;
            if f[i].b=0 then
            begin
                f[i].x2:=f[i].c/f[i].a;f[i].y2:=random(100)+1;
            end
            else
            begin
                f[i].x2:=0;f[i].y2:=f[i].c/f[i].b;
            end;
        end;
        for i:=1 to n-1 do
        for j:=i+1 to n do
        begin
            s1:=(f[j].x1-f[i].x1)*(f[j].y2-f[i].y1)-(f[j].y1-f[i].y1)*(f[j].x2-f[i].x1);
            s2:=(f[j].x1-f[i].x2)*(f[j].y2-f[i].y2)-(f[j].y1-f[i].y2)*(f[j].x2-f[i].x2);
            if s1=s2 then continue;
            inc(l);
            a[l].x:=(s2*f[i].x1-s1*f[i].x2)/(s2-s1);
            a[l].y:=(s2*f[i].y1-s1*f[i].y2)/(s2-s1);
        end;
        for i:=1 to l do
        begin
            u:=true;
            for j:=1 to n do
            if f[j].a*a[i].x+f[j].b*a[i].y>f[j].c then
            begin
                u:=false;break;
            end;
            if u then
            begin
                inc(m);
                b[m]:=a[i];
                if b[m].x=0 then b[m].x:=0;
                if b[m].y=0 then b[m].y:=0;
            end;
        end;
        d.y:=maxlongint;
        for i:=1 to m do
        if (b[i].y<d.y)or((b[i].y=d.y)and(b[i].x<d.x)) then
            d:=b[i];
        for i:=1 to m do
        if (d.x<>b[i].x)or(d.y<>b[i].y) then
            b[i].c:=(b[i].x-d.x)/sqrt(sqr(b[i].x-d.x)+sqr(b[i].y-d.y))
        else b[i].c:=-1;
        x:=d.x;
        for i:=1 to m do
        for j:=1 to m-1 do
        if (b[j].c>b[j+1].c)or((b[j].c=b[j+1].c)and(abs(b[j].x-x)>abs(b[j+1].x-x))) then
        begin
            d:=b[j];b[j]:=b[j+1];b[j+1]:=d;
        end;
        for i:=1 to m do
        if (i=1)or(b[i].x<>b[i-1].x)or(b[i].y<>b[i].y) then
            writeln(b[i].x:0:2,' ',b[i].y:0:2);
    end.

    Miller-Rabin

    function pow( a, d, n:longint ):longint;
    begin
         if d=0 then exit(1)
         else if d=1 then exit(a)
         else if d and 1=0 then exit( pow( a*a mod n, d div 2, n) mod n)
         else exit( (pow( a*a mod n, d div 2, n) * a) mod n);
    end;
    function IsPrime( a,n:longint ):boolean;
    var
         d,t:longint;
    begin
         if n=2 then exit(true);
         if (n=1) or (n and 1=0) then exit(false);
         d:=n-1;
         while d and 1=0 do d:=d shr 1;
         t:=pow( a, d, n );
         while ( d<>n-1 ) and ( t<>1 ) and ( t<>n-1 ) do
         begin
              t:=(t * t)mod n;
              d:=d shl 1;
         end;
         exit( (t=n-1) or (d and 1=1) );
    end;

    KMP

    var
        s1,s2:string;
        i,j,l1,l2:longint;
        a:array[1..100]of longint;
    begin
        readln(s1);readln(s2);
        l1:=length(s1);l2:=length(s2);
        for i:=2 to l1 do
        if s1[a[i-1]+1]=s1[i] then
            a[i]:=a[i-1]+1
        else a[i]:=0;
        i:=1;j:=1;
        while (i<=l1)and(j<=l2) do
            if s1[i]=s2[j] then
            begin
                 inc(i);inc(j);
            end
            else
            if i=1 then
                inc(j)
            else i:=a[i-1]+1;
        if i>l1 then
            write(true)
        else write(false);
    end.

    January 06

    dinic

    uses math;
    const max=2000;
    type
        link=^rec;
        rec=record
            i:longint;
            point:link;
        end;
        ss=record
            min,i:longint;
            p:link;
        end;
    var
        f,c:array[1..max,1..max]of longint;
        g:array[1..max,1..max]of boolean;
        h:array[1..max]of boolean;
        a:array[0..max]of ss;
        d,b:array[1..max]of longint;
        v:array[1..max]of link;
        n,m,s,t,res:longint;   

    procedure readp;
    var
        i,j,k,l:longint;
        p:link;
    begin
        readln(n,m,s,t);
        for i:=1 to m do
        begin
            readln(j,k,l);
            if (not g[j,k])and(j<>k) then
            begin
                new(p);
                p^.i:=k;p^.point:=v[j];v[j]:=p;
                new(p);
                p^.i:=j;p^.point:=v[k];v[k]:=p;
                g[j,k]:=true;g[k,j]:=true;
            end;
            inc(c[j,k],l);
        end;
    end;

    procedure bfs;//从汇点开始标号
    var
        l,r,now:longint;
        p:link;
    begin
        b[1]:=t;l:=0;r:=1;h[t]:=true;
        repeat
            inc(l);now:=b[l];
            p:=v[now];
            while p<>nil do
            begin
                if (not h[p^.i])and(c[p^.i,now]>0) then
                begin
                    inc(r);b[r]:=p^.i;
                    d[p^.i]:=d[now]+1;
                    h[p^.i]:=true;
                end;
                p:=p^.point;
            end;
        until l=r;
    end;

    procedure dinic;
    var
        r,now,i,k,l:longint;
        p:link;
    begin
        fillchar(h,sizeof(h),0);
        r:=0;
        a[r].i:=s;a[r].min:=maxlongint;
        p:=v[s];h[s]:=true;
        while d[s]<n do
        begin
            now:=a[r].i;
            while (p<>nil)and((h[p^.i])or(d[p^.i]+1<>d[now])or(c[now,p^.i]-f[now,p^.i]+f[p^.i,now]=0)) do
                p:=p^.point;
            if p<>nil then
            begin
                h[p^.i]:=true;
                inc(r);
                a[r].i:=p^.i;a[r].p:=p;
                a[r].min:=min(a[r-1].min,c[now,p^.i]-f[now,p^.i]+f[p^.i,now]);
                if p^.i=t then
                begin
                    k:=a[r].min;
                    inc(res,k);
                    for i:=1 to r do
                    begin
                        inc(f[a[i-1].i,a[i].i],k);
                        if f[a[i-1].i,a[i].i]>c[a[i-1].i,a[i].i] then
                        begin
                            dec(f[a[i].i,a[i-1].i],f[a[i-1].i,a[i].i]-c[a[i-1].i,a[i].i]);
                            f[a[i-1].i,a[i].i]:=c[a[i-1].i,a[i].i];
                        end;
                        dec(a[i].min,k);
                    end;
                    while a[r].min=0 do
                    begin
                        h[a[r].i]:=false;
                        dec(r);
                    end;
                    p:=a[r+1].p^.point;continue;
                end;
                p:=v[p^.i];
            end
            else
            begin
                p:=v[now];d[now]:=n;
                while p<>nil do
                begin
                    if (not h[p^.i])and(c[now,p^.i]-f[now,p^.i]+f[p^.i,now]>0)and(d[p^.i]+1<d[now]) then
                        d[now]:=d[p^.i]+1;
                    p:=p^.point;
                end;
                p:=v[now];
                if (d[now]=n)and(r<>0) then
                begin
                    p:=a[r].p^.point;
                    dec(r);
                end;
            end;
        end;
    end;

    begin
        readp;
        bfs;
        dinic;
        writeln(res);
    end.

    November 12

    01背包前k优值(不一定装满)

    type
        ss=array[1..100]of longint;
    var
        f:array[0..10000]of ss;
        a,w:array[1..10000]of longint;
        v,i,j,n,k:longint;
    function max(a,b:ss;x:longint):ss;
    var
        i,j,l:longint;
        c:ss;
    begin
        i:=1;j:=1;l:=0;
        while l<k do
        begin
            inc(l);
            if a[i]<b[j]+x then
            begin
                c[l]:=b[j]+x;inc(j);
            end
            else
            begin
                c[l]:=a[i];inc(i);
            end;
        end;
        exit(c);
    end;
    begin
        read(k,v,n);
        for i:=1 to n do
            readln(a[i],w[i]);
        for i:=0 to v do
        for j:=1 to k do
            f[i,j]:=-maxlongint;
        f[0,1]:=0;
        for i:=1 to n do
        begin
            for j:=v downto a[i] do              {如果是完全背包则变成 for j:=a[i] to v 即可}
                f[j]:=max(f[j],f[j-a[i]],w[i]);
            for j:=a[i]+1 to v do                  {如果是"一定装满"则直接去掉此for语句即可}
                f[j]:=max(f[j],f[j-1],0);  
        end;
        for i:=1 to k do
        if f[v,i]<0 then break
        else write(f[v,i],' ');
        writeln;
    end.

    组合数C(n,r)

    递推式(不加高精,不加记忆化)

    var
        n,r:longint;
    function C(n,r:longint):longint;
    begin
        if (n=r)or(r=0) then exit(1)
        else exit(C(n-1,r-1)+C(n-1,r));
    end;
    begin
        readln(n,r);
        writeln(C(n,r));
    end.

    通项式-直接高精

    var
        a:array[0..100000]of integer;
        n,r,i,j,k,l,o:longint;
    begin
        readln(n,r);
        if r>n-r then r:=n-r;
        a[0]:=1;a[1]:=1;
        for i:=n-r+1 to n do
        begin
            k:=0;
            inc(a[0],trunc(ln(i)/ln(10))+1);
            for j:=1 to a[0] do
            begin
                o:=a[j]*i+k;
                a[j]:=o mod 10;
                k:=o div 10;
            end;
            while a[a[0]]=0 do dec(a[0]);
        end;
        for i:=2 to r do
        begin
            o:=0;
            for j:=a[0] downto 1 do
            begin
                o:=o*10+a[j];
                a[j]:=o div i;
                o:=o mod i;
            end;
            while a[a[0]]=0 do dec(a[0]);
        end;
        for i:=a[0] downto 1 do
            write(a[i]);
        writeln;
    end.

    通项式-分解质因数

    type
        ss=record
            i,x:longint;
        end;
    var
        h:array[1..100000]of boolean;
        g,f:array[1..100000]of ss;
        a:array[0..100000]of integer;
        r,i,j,k,l,n:longint;
        x,o:int64;
    function bp(b,p:longint):int64;
    var
        x:int64;
    begin
        if p=0 then exit(1)
        else
        begin
            x:=sqr(bp(b,p shr 1));
            if (p and 1)=1 then x:=x*b;
            exit(x);
        end;
    end;
    begin
        readln(n,r);
        if r>n-r then r:=n-r;
        l:=0;
        for i:=2 to n do
        if not h[i] then
        begin
            h[i]:=true;
            inc(l);f[l].i:=i;
            g[i].i:=i;g[i].x:=1;
            if i<=r then f[l].x:=-1
            else if i>n-r then f[l].x:=1;
            for j:=2 to n div i do
            begin
                h[j*i]:=true;
                g[j*i].i:=i;
                if g[j].i<>i then
                    g[j*i].x:=1
                else g[j*i].x:=g[j].x+1;
                if j*i<=r then dec(f[l].x,g[j*i].x)
                else if j*i>n-r then inc(f[l].x,g[j*i].x);
            end;
        end;
        a[0]:=1;a[1]:=1;
        for i:=1 to l do
        begin
            x:=bp(f[i].i,f[i].x);
            k:=0;
            inc(a[0],trunc(ln(x)/ln(10))+1);
            for j:=1 to a[0] do
            begin
                o:=a[j]*x+k;
                a[j]:=o mod 10;
                k:=o div 10;
            end;
            while a[a[0]]=0 do dec(a[0]);
        end;
        for i:=a[0] downto 1 do
            write(a[i]);
        writeln;
    end.