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.