jzoj1365 无限序列

Description

  我们按以下方式产生序列:   1、 开始时序列是: “1” ;   2、 每一次变化把序列中的 “1” 变成 “10” ,”0” 变成 “1”。   经过无限次变化,我们得到序列”1011010110110101101…”。   总共有 Q 个询问,每次询问为:在区间A和B之间有多少个1。   任务:写一个程序回答Q个询问

Input

  第一行为一个整数Q,后面有Q行,每行两个数用空格隔开的整数a, b。

Output

  共Q行,每行一个回答

Sample Input

1

2 8

Sample Output

4

Data Constraint

【数据范围】 •1 <= Q <= 5000

•1 <= a <= b < 2^63

算法讨论

看看数据范围,意识到存在某些规律,手推一哈
1
10
101
10110
10110101
1011010110110
101101011011010110101
个数为:1 2 3 5 8 13 21...
1的个数为:1 1 2 3 5 8 13...
而且前面的是后面的前缀,而且这个数列可以组成任何正整数。
var
  a,b:array[1..500] of qword;
  x,y:array[1..6000] of qword;
  l,q:longint;
  xx,yy:qword;
function find(z:qword):qword;
var
  i:longint;
begin
  find:=0;
  for i:=l downto 1 do
    if z>=b[i] then
      begin
        find:=find+a[i];
        z:=z-b[i];
      end;
end;
var
  i:longint;
begin
  readln(q);
  for i:=1 to q do
    begin
      readln(x[i],y[i]);
      if y[i]>yy then yy:=y[i];
    end;
  a[1]:=1;a[2]:=1;
  b[1]:=1;b[2]:=2;l:=2;
  while b[l]<=yy do
    begin
      inc(l);
      a[l]:=a[l-1]+a[l-2];
      b[l]:=b[l-1]+b[l-2];
    end;
  for i:=1 to q do
    writeln(find(y[i])-find(x[i]-1));
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值