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

来源:互联网 发布:windows createfile 编辑:程序博客网 时间:2024/06/05 10:17

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 xor 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.



0 0