李总不知从哪里找的鬼题——无限序列

先上题目:

1、无限序列
infinit.pas/c/cpp
1s / 128M
[问题描述]
我们按以下方式产生序列:
1、 开始时序列是: "1" ;
2、 每一次变化把序列中的 "1" 变成 "10" ,"0" 变成 "1"。
经过无限次变化,我们得到序列"1011010110110101101..."。
总共有 Q 个询问,每次询问为:在区间 A 和 B 之间有多少个 1。
请写一个程序回答 Q 个询问。
[输入数据]
第一行为一个整数 Q,后面有 Q 行,每行两个数用空格隔开的整数 a, b。
[输出数据]
共 Q 行,每行一个回答
[输入样例]
1
2 8
[输出样例]
4
[数据范围]
1 <= Q <= 5000
1 <= a <= b < 2^63

------------------------------------------------------------------分割线-----------------------------------------------------------------------

本来一开始一位是要根据数列规律来计算,于是找规律找循环找了半天,最后看了解析才TM地发现居然是斐波那契。。。。。。好吧,先看看下面这几组序列:

1

10

101

10110

10110101

1011010110110

101101011011010110101

......

看了这几个序列是不是发现了什么?对,第i个序列就是在第i-1个序列后面接上第i-2个序列,所以。。。。。。斐波那契。。。。。。

不过要想实现还是需要点思维,必须找到一个斐波那契数f[n],使得a<=f[n-1]<b<f[n],然后将a,b分为两段,直到每一段的长度都是斐波那契数为止(因为只有这样才能求出第a到第b个数之间的1的个数)

具体还是看下代码吧(其实就是我懒):

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n;
ll a,b,f[93],ff[93];
/*切记,斐波那契数到第92个就会爆long long
而这一题的范围正好是long long以内,所以就开到92*/ ll find(ll num,ll x,ll y) {
if(x==0||y==0) return 0; if(num==1) return 1; if(num==2) return x==2?0:1; if(x==1&&y==f[num]) return ff[num]; ll cnt=0; if(x<=f[num-1]) { if(y>f[num-1]) cnt=cnt+find(num-1,x,f[num-1])+find(num-1,1,y-f[num-1]); else cnt+=find(num-1,x,y); } else cnt+=find(num-2,x-f[num-1],y-f[num-1]); return cnt; } int main() { freopen("infinit.in","r",stdin); freopen("infinit.out","w",stdout); scanf("%lld",&n); f[1]=ff[1]=1; f[2]=2;ff[2]=1; for(ll i=3;i<=92;i++) { f[i]=f[i-1]+f[i-2]; ff[i]=ff[i-1]+ff[i-2]; } for(ll i=1;i<=n;i++) { scanf("%lld%lld",&a,&b); ll ans=find(92,a,b); printf("%lld ",ans); } return 0; }

 

蒟蒻写博客不易,如果有误还请大佬们提出
如需转载,请署名作者并附上原文链接,蒟蒻非常感激
名称:HolseLee
博客地址:www.cnblogs.com/cytus
个人邮箱:1073133650@qq.com
原文地址:https://www.cnblogs.com/cytus/p/7656855.html