现在的位置: 首页 > 综合 > 正文

apex (卓亮)

2018年01月15日 ⁄ 综合 ⁄ 共 1080字 ⁄ 字号 评论关闭

http://www.tsinsen.com/ViewGProblem.html?gpid=-1000001306

【题意】

定义x[1]=1,x[2k]=-x[k],x[2k-1]=(-1)^(k+1) x[k](k>1),回答三类询问

1、求xn

2、判断x1+..+xn的正负

3、求x1+..+xn

【输入】

第一行q,表示询问个数

接下来q行,每行两个数字c、n

表示询问类型和n(n<=10^8)

【输出】

询问1、3输出值即可

询问2输出“+”或“-”或“0”

唯一做出来的一道集训队题啊,最简单的一道了

而且是观察规律得出的结论

首先我把前64个的值打了一下表,然后观察

发现对于[1..4],[1..1]=[3..3],[2..2]=-[4..4]  (=的意思是序列相同,=-是序列的值互为相反数)

拉长以后发现还具有如此规律,例如

对于[1..128],[1..32]=[65..96],[33..64]=-[97..128]

利用这个结论,就可以在logn时间内求x[1]+..x[n]了

如果知道这个还是不会求的话……何必勉强自己做集训队互测题呢……

program apex;
var
  q,c,i,j,k:longint;
  one,o,n:int64;
  sum:array [0..64] of int64;

function quick (now:int64):int64;
var
  k:longint;
  ans:int64;

begin
  if now=0 then exit(0);
  if now=1 then exit(1);
  if now=2 then exit(0);
  k:=trunc(ln(now)/ln(2));
  if one shl k=now then exit(sum[k]);
  ans:=sum[k];
  now:=now-(one shl k);
  if now<=one shl (k-1) then exit(ans+quick(now));
  exit(-(quick(now)-sum[k-1])+ans+sum[k-1]);
end;

begin
  one:=1;
  sum[0]:=1;
  sum[1]:=0;
  for i:=2 to 63 do
    sum[i]:=sum[i-2]*2;
  read(q);
  for i:=1 to q do
    begin
      read(c,n);
      case c of
        1:writeln(quick(n)-quick(n-1));
        2:begin
            o:=quick(n);
            if o=0 then writeln(0)
                   else
            if o>0 then writeln('+')
                   else writeln('-');
          end;
        3:writeln(quick(n));
      end;
    end;
end.

【上篇】
【下篇】

抱歉!评论已关闭.