您的位置:首页 > 其它

noipday3提高组模拟题————解题报告

2015-10-20 20:57 288 查看
1.方程式

思路:直接枚举根,然后通过逆向多项式乘法提出这个根因式。

参考程序:

var

  t,n,i,j:longint;

  a,b:array[0..11000]of longint;

function calc(k:longint):longint;

var

  i,tt:longint;

begin

  calc:=0;tt:=1;

  for i:=1 to n do

   begin

     calc:=calc+a[i]*tt;

    // if k=1 then writeln(calc);

     tt:=tt*k;

   end;

end;

procedure change(k:longint);

var

  i:longint;

begin

  b[1]:=a[1] div (-k);

  for i:=2 to n-1 do

   b[i]:=(b[i-1]-a[i])div k;

  n:=n-1;

  a:=b;

end;

begin

  assign(input,'equation.in');reset(input);

  assign(output,'equation.out');rewrite(output);

  read(n);

  n:=n+1;

  for i:=1 to n do read(a[i]);

  //for i:=1 to n shr 1 do begin t:=a[i];a[i]:=a[n-i+1];a[n-i+1]:=t;end;

 for i:=1 to 20 do

   while calc(i)=0 do

    begin

      write(i,' ');

      change(i);

      //for j:=1 to n do write(a[j],' ');writeln;

    end;

  close(input);close(output);

end.

2.高维宇宙

思路:标程是状压dp,我想的是二分图匹配。

            此题中质数只能是由奇数加偶数,因此可将一般图弄为二分图,网络流即可。

参考程序(标准的dinic算法,只有90分,据目测还有一个数据可能有问题):

type

  edge=record

         tt,v,next:longint;

       end;

var

  e:array[0..110000]of edge;

  b,level,head,q,a:array[0..110000]of longint;

  cnt,cnt1,cnt2,n:longint;

procedure openfile;

begin

  assign(input,'prime.in');reset(input);

  assign(output,'prime.out');rewrite(output);

end;

procedure closfile;

begin

  close(input);close(output);

end;

procedure printf(k:longint);

begin

  write(k);

end;

function min(a,b:longint):longint;

begin

  if a<b then exit(a);

  exit(b);

end;

procedure init;

var

  i,x:longint;

begin

  readln(n);

  for i:=1 to n do

   begin

     read(x);

     if x and 1=1 then begin cnt1:=cnt1+1;a[cnt1]:=x;end

      else begin cnt2:=cnt2+1;b[cnt2]:=x;end;

   end;

end;

procedure insert(u,v,w:longint);

begin

  cnt:=cnt+1;

  e[cnt].tt:=v;

  e[cnt].v:=w;

  e[cnt].next:=head[u];

  head[u]:=cnt;

end;

procedure build;

var

  ok:array[0..2200]of boolean;

  i,j:longint;

begin

  ok[1]:=true;

  for i:=2 to trunc(sqrt(2100)) do//第二版::大家注意到了么?去掉之后就是。。。。Accepted......

   if not ok[i] then

    for j:=2 to 2100 div i do

     ok[i*j]:=true;

  for i:=1 to cnt1 do

   for j:=1 to cnt2 do

    if not ok[a[i]+b[j]] then

     begin

       //writeln(i,' ',j+cnt1);

       insert(i,j+cnt1,1);

       insert(j+cnt1,i,0);

     end;

  for i:=1 to cnt1 do begin {writeln(0,' ',i);}insert(0,i,1);insert(i,0,0);end;

  for i:=1 to cnt2 do begin {writeln(i,' ',n+1);}insert(i,n+1,1);insert(n+1,i,0);end;

end;

function bfs:boolean;

var

  h,t,i,now:longint;

begin

  fillchar(level,sizeof(level),$ff);

  h:=0;t:=1;q[1]:=0;level[0]:=0;

  while h<t do

   begin

     h:=h+1;

     now:=q[h];

     i:=head[now];

     while i>0 do

      begin

        if (e[i].v>0)and(level[e[i].tt]=-1) then

         begin

           t:=t+1;

           q[t]:=e[i].tt;

           level[e[i].tt]:=level[now]+1;

         end;

        i:=e[i].next;

      end;

   end;

  if level[n+1]=-1 then exit(false);

  exit(true);

end;

function dfs(x,f:longint):longint;

var

  i,used,w:longint;

begin

  if x=n+1 then exit(f);

  used:=0;i:=head[x];

  while i>0 do

   begin

     if (e[i].v>0)and(level[e[i].tt]=level[x]+1) then

      begin

        w:=f-used;

        w:=dfs(e[i].tt,min(e[i].v,w));

        e[i].v:=e[i].v-w;

        e[i xor 1].v:=e[i x
4000
or 1].v+w;

        used:=used+w;

        if used=f then exit(f);

      end;

     i:=e[i].next;

   end;

  if used=0 then level[x]:=-1;

  exit(used);

end;

procedure dinic;

const

  INF=maxlongint shr 2;

var

  maxflow:longint;

begin

  maxflow:=0;

  while bfs do

   maxflow:=maxflow+dfs(0,INF);

  printf(maxflow);

end;

procedure solve;

begin

  dinic;

end;

procedure main;

begin

  openfile;

  init;

  build;

  solve;

  closfile;

end;

begin

  main;

end.

第二版::发现问题之所在————筛质数打错了,为什么要开根号呢?

此题可用状压dp写:

var

  e:array[0..101000]of record

                        x,n:longint;

                       end;

  l,t,nx,x,k,ans,b0,tt,a0,i,j,n:longint;

  key:array[0..50,0..2001000]of boolean;

  a,b:array[0..101000]of longint;

  ok:array[0..22000]of boolean;

function min(a,b:longint):longint;

begin if a<b then exit(a);exit(b);end;

function max(a,b:longint):longint;

begin if a>b then exit(a);exit(b);end;

procedure build;

var

  i,j:longint;

begin

  ok[1]:=true;

  fillchar(ok,sizeof(ok),0);

  for i:=2 to 21000 do

   if not ok[i] then

    for j:=2 to 21000 div i do

     ok[i*j]:=true;

end;

procedure add(x,y:longint);

begin

  l:=l+1;//writeln(x,' ',y);

  e[l].x:=y;e[l].n:=e[x].n;e[x].n:=l;

end;

function count(k:longint):longint;

begin

  count:=0;

  while k>0 do

   begin

     count:=count+k and 1;

     k:=k shr 1;

   end;

end;

begin

  assign(input,'prime.in');reset(input);

  assign(output,'prime.out');rewrite(output);

  readln(n);

  for i:=1 to n do

   begin

     read(tt);

     if tt and 1=1 then begin a0:=a0+1;a[a0]:=tt;end

      else begin b0:=b0+1;b[b0]:=tt;end;

   end;

  nx:=min(a0,b0);

  if b0<a0 then

   begin

     for i:=0 to nx do

      begin

        t:=a[i];a[i]:=b[i];b[i]:=t;

      end;

     t:=a0;a0:=b0;b0:=t;

     for i:=nx+1 to b0 do

      b[i]:=a[i];

   end;

  l:=n;

  build;

  for i:=1 to b0 do

    for j:=1 to a0 do

     if not ok[b[i]+a[j]] then add(i,j);

  key[0,0]:=true;

  for i:=0 to b0-1 do

   for j:=0 to 1<<nx-1 do

    if key[i,j] then

     begin

       key[i+1,j]:=true;

       x:=e[i+1].n;

       while x>0 do

        begin

          k:=e[x].x-1;

          key[i+1,j or (1<<k)]:=true;

          x:=e[x].n;

        end;

     end;

  ans:=0;

  for j:=0 to 1<<nx-1 do

   if key[b0,j] then ans:=max(ans,count(j));

  write(ans);

  close(input);close(output);

end.

3.麻将

思路:枚举打出的牌,再枚举要听的牌,深搜判断胡没胡即可。

参考程序:

var

  {debug:array[0..1000]of record

                          no,num,flag:longint;

  end;}

  cnt:longint;

  c,b,inq,x,a:array[0..1000]of longint;

procedure openfile;

begin

  assign(input,'mahjong.in');reset(input);

  assign(output,'mahjong.out');rewrite(output);

end;

procedure closfile;

begin

  close(input);close(output);

end;

procedure init;

var

  num,ch1,ch2:char;

  i:longint;

begin

  for i:=1 to 14 do

   begin

     read(num,ch1,ch2);

     a[i]:=(ord(num)-48)*10+ord(ch1='p')+ord(ch1='w')*2;

     x[a[i]]:=x[a[i]]+1;

   end;

  //s=0 p=1 w=2

end;

procedure prepare;

var

  i:longint;

begin

  for i:=1 to 9 do

   begin

     cnt:=cnt+1;

     b[cnt]:=i*10;

     b[cnt+1]:=i*10+1;

     b[cnt+2]:=i*10+2;

     cnt:=cnt+2;

   end;

end;

{procedure print;

var

  i:longint;

begin

  for i:=1 to 4 do with debug[i] do writeln(no,' ',num,' ',flag);

  for i:=1 to 14 do write(inq[c[i]],' ');writeln;

end;}

function dfs(last,step:longint):boolean;

var

  i,u:longint;

  bool:boolean;

begin

  if last=2 then

   begin

     for i:=1 to 14 do

      if inq[c[i]]=2 then exit(true);

     exit(false);

   end;

  bool:=false;

  for i:=1 to 14 do

    begin

      if inq[c[i]]>2 then

       begin

         inq[c[i]]:=inq[c[i]]-3;

         //debug[step].no:=i;debug[step].num:=c[i];debug[step].flag:=1;

         bool:=bool or dfs(last-3,step+1);

         inq[c[i]]:=inq[c[i]]+3;

       end;//duizi

      if bool then exit(true);

      if (inq[c[i]]>0)and(inq[c[i]+10]>0)and(inq[c[i]+20]>0) then

       begin

         inq[c[i]]:=inq[c[i]]-1;inq[c[i]+10]:=inq[c[i]+10]-1;inq[c[i]+20]:=inq[c[i]+20]-1;

         //debug[step].no:=i;debug[step].num:=c[i];debug[step].flag:=2;

         bool:=bool or dfs(last-3,step+1);

         inq[c[i]]:=inq[c[i]]+1;inq[c[i]+10]:=inq[c[i]+10]+1;inq[c[i]+20]:=inq[c[i]+20]+1;

       end;//shunzi

      if bool then exit(true);

    end;

  exit(false);

end;

function check(tno,k:longint):boolean;

var tlt:longint;

begin

  inq:=x;c:=a;

  inq[k]:=inq[k]+1;inq[a[tno]]:=inq[a[tno]]-1;

  c[tno]:=k;

  {if k=b[1] then

   begin

     for tlt:=1 to 14 do write(c[tlt]:4);writeln;

     for tlt:=1 to 14 do write(inq[c[tlt]]:4);writeln;writeln;

   end;}

  exit(dfs(14,1));

end;

procedure solve;

var

  max,tt,no,i,j,tlt:longint;

begin

  max:=0;no:=0;

  for i:=1 to 14 do

   begin

     //s=0 p=1 w=2

     tt:=0;

     for j:=1 to cnt do

      if inq[b[j]]<4 then

       if check(i,b[j]) then

        begin

          tt:=tt+5-inq[b[j]];

          //if i=9 then writeln(b[j],' ',tt);

        end;

     if tt>max then begin no:=i;max:=tt;end;

   end;

  write(no,' ',max);

end;

procedure main;

begin

  openfile;

  init;

  prepare;

  solve;

  closfile;

end;

begin

  main;

end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: