JZOJ 4.1 B组 无限序列

本文介绍了一种通过递归函数实现的算法,该算法能够高效地计算一个特殊无限序列中指定区间内数字1的出现次数。序列由简单的规则生成:初始为1,随后将每个1替换为10,0替换为1,形成一个类似斐波那契数列的结构。文章提供了一个完整的程序示例,展示了如何处理多个查询,并给出了示例输入输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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


一种类似于斐波那契的东西
先用一个z来存前缀和
再求这个数列包含多少个1


代码如下:

var   n,i:longint;
      x,y:int64;
      z:array[-1..91] of int64;

function find(l:int64;k:longint):int64;
begin
  if l=0 then exit(0);
  find:=0;
  if l=z[k] then find:=z[k-1]else if l<=z[k-1] then find:=find(l,k-1) else find:=z[k-2]+find(l-z[k-1],k-2);
end;

begin
  readln(n);
  z[0]:=1;
  z[1]:=1;
  for i:=2 to  91 do z[i]:=z[i-1]+z[i-2];
  for i:=1 to n do
    begin
      read(x,y);
      writeln(find(y,91)-find(x-1,91));
    end;
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值