[BZOJ2523][CTSC2001]聪明的学生 递推

来源:互联网 发布:止水螺栓算法 编辑:程序博客网 时间:2024/05/18 01:55

原来这还能出成题。。。
我也不会证为什么每次都是数值最大的学生先猜出来,但感性yy一下是可以出来的。
首先一个学生猜不出来,无非就是在x+y, |x-y|中犹豫,但是我们观察发现,当x=y时,|x-y|=0,他是可以立即猜出自己的数是x+y的。
然后在想想,假如A,B,C三人的数为(x,2x,3x),如果B没有猜出来,那么C就可以肯定自己的数不是x,于是就猜出来了。
好像可以一直推下去。。。
设F(x,y,z)为猜出(x,y,z)所需要的轮数,那么F(x,y,x+y)=F[x,y,|x-y|]+1 or 2。到底是1还是2,取决于到x+y猜数还有一轮还是两轮。
写的时候这样好写,F[x,y,t]表示最大的数在t学生上,然后t后面的是x,在后面的是y,于是分x = y,x < y,x > y三种情况讨论即可。
看代码里的pd函数。
代码:

var  n,m,i,t0,t1,t2,tot:longint;  pre:array[0..2]of longint=(2,0,1);  suc:array[0..2]of longint=(1,2,0);  ans:array[0..30010,0..2]of longint;function pd(x,y,t:longint):boolean;var  rnd,nowx,nowy:longint;begin  rnd:=n;  while rnd>0 do  begin    if x=y then exit(rnd=t+1);    if x>y then    begin      nowx:=y;      nowy:=x-y;      dec(rnd,2);      t:=suc[t];    end    else    begin      nowx:=y-x;      nowy:=x;      dec(rnd,1);      t:=pre[t];    end;    x:=nowx;    y:=nowy;  end;  exit(false);end;begin  while true do  begin    readln(n,m);    if (n=-1)and(m=-1) then break;    t1:=n mod 3;    t0:=pre[t1];    t2:=suc[t1];    tot:=0;    for i:=1 to m-1 do      if pd(i,m-i,t0) then      begin        inc(tot);        ans[tot,t0]:=m;        ans[tot,t1]:=i;        ans[tot,t2]:=m-i;      end;    writeln(tot);    if t0=1 then for i:=tot downto 1 do writeln(ans[i,0],' ',ans[i,1],' ',ans[i,2])    else for i:=1 to tot do writeln(ans[i,0],' ',ans[i,1],' ',ans[i,2]);  end;end.
0 0
原创粉丝点击