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

原来这还能出成题。。。
我也不会证为什么每次都是数值最大的学生先猜出来,但感性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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值