【题目描述】
说当初大闹天宫的猴头反斗精——孙悟空来到了21世纪。当他通过时空隧道来到21世纪时才发现世界发生了翻天覆地的变化。于是他决定来中国的泰山学艺。他在海南腾云驾雾来到泰山脚下,谁知脚下却有两个人把守。他走上前对他们说:“喂!我要见你们的师傅——粉面大秃驴。”那两个人没有搭理他,反而说:“我们的师傅岂是你这个毛猴想见就见的!”孙悟空听了,心中很是愤怒,心想:当初我大闹天宫时,怕过谁!而现在却让这两个毛孩训斥,哼!给你们点厉害瞧瞧。接着,他就掏出金箍棒朝那两个人砸去。可是谁知刚砸到他们面前,却被一道光给挡了回来。原来他们的面前都有一道防护层。“哼!21世纪还用武力解决问题,白痴!”他们不懈的说,“21世纪是智慧的时代,不过,看你是孙悟空的面子上,你只要答对我们的问题,我便放你进去见我们的师傅。”悟空听了,无奈的点了点头,看来只有这样了。“好,猴头,你听好了!这里有一个桃子,我们以下列的方式对它进行变换:
①开始时,只有一个桃子;
②每一次变换,把其中的桃子变成桃子和梨,其中的梨变成桃子。
我们用‘T’表示桃子,用‘L’表示梨,则经过无数次的变换,我们得到如下字符串“TLTTLTLTTLTTLTLTTLT……”。现在你的任务是:每次给你n个询问,每个询问为:在区间a和b之间有多少个
桃子。”孙悟空听了傻了眼,他一个从石头里蹦出来的猴子,哪会这么多东西。可是他必须要去见泰山宗,怎么办呢?看来只有求助于你们了。
【输入格式】
第一行是一个整数n,表示有n次提问,后面有n行,每行有两个整数a和b,用空格隔开。
对于100%的数据
1<=n<=5000
1<=a<=b<2^63
【输出格式】
共n行,每行有一个回答,表示在这个区间内有多少个桃子。
【输入样例】
1
2 8
【输出样例】
4
这道题,照规则模拟一下,发现是一个斐波那契数列。如下:
字符串: 总长: T个数: L个数
T 1 1 0
TL 2 1 1
TLT 3 2 1
TLTTL 5 3 2
TLTTLTLT 8 5 3
TLTTLTLTTLTTL 13 8 5
TLTTLTLTTLTTLTLTTLTLT 21 13 8
这样,我们发现这是一个斐波那契数列。不论是长度,还是T个数,甚到是字符串本身,甚至于L的个数,都满足f[i]=f[i-1]+f[i-2]。
于是,对于一个区间[a,b],我们可以这样算出答案:ans=Cal(b)-Cal(a-1)。
如何计算呢
对于区间[a, b]计算b和计算a同理
以计算b为例
设a为斐波那契数列 则b可以拆分为k个斐波那契数的和
而T的个数就是那k个斐波那契数的前一项的和
说当初大闹天宫的猴头反斗精——孙悟空来到了21世纪。当他通过时空隧道来到21世纪时才发现世界发生了翻天覆地的变化。于是他决定来中国的泰山学艺。他在海南腾云驾雾来到泰山脚下,谁知脚下却有两个人把守。他走上前对他们说:“喂!我要见你们的师傅——粉面大秃驴。”那两个人没有搭理他,反而说:“我们的师傅岂是你这个毛猴想见就见的!”孙悟空听了,心中很是愤怒,心想:当初我大闹天宫时,怕过谁!而现在却让这两个毛孩训斥,哼!给你们点厉害瞧瞧。接着,他就掏出金箍棒朝那两个人砸去。可是谁知刚砸到他们面前,却被一道光给挡了回来。原来他们的面前都有一道防护层。“哼!21世纪还用武力解决问题,白痴!”他们不懈的说,“21世纪是智慧的时代,不过,看你是孙悟空的面子上,你只要答对我们的问题,我便放你进去见我们的师傅。”悟空听了,无奈的点了点头,看来只有这样了。“好,猴头,你听好了!这里有一个桃子,我们以下列的方式对它进行变换:
①开始时,只有一个桃子;
②每一次变换,把其中的桃子变成桃子和梨,其中的梨变成桃子。
我们用‘T’表示桃子,用‘L’表示梨,则经过无数次的变换,我们得到如下字符串“TLTTLTLTTLTTLTLTTLT……”。现在你的任务是:每次给你n个询问,每个询问为:在区间a和b之间有多少个
桃子。”孙悟空听了傻了眼,他一个从石头里蹦出来的猴子,哪会这么多东西。可是他必须要去见泰山宗,怎么办呢?看来只有求助于你们了。
【输入格式】
第一行是一个整数n,表示有n次提问,后面有n行,每行有两个整数a和b,用空格隔开。
对于100%的数据
1<=n<=5000
1<=a<=b<2^63
【输出格式】
共n行,每行有一个回答,表示在这个区间内有多少个桃子。
【输入样例】
1
2 8
【输出样例】
4
这道题,照规则模拟一下,发现是一个斐波那契数列。如下:
字符串: 总长: T个数: L个数
T 1 1 0
TL 2 1 1
TLT 3 2 1
TLTTL 5 3 2
TLTTLTLT 8 5 3
TLTTLTLTTLTTL 13 8 5
TLTTLTLTTLTTLTLTTLTLT 21 13 8
这样,我们发现这是一个斐波那契数列。不论是长度,还是T个数,甚到是字符串本身,甚至于L的个数,都满足f[i]=f[i-1]+f[i-2]。
于是,对于一个区间[a,b],我们可以这样算出答案:ans=Cal(b)-Cal(a-1)。
如何计算呢
对于区间[a, b]计算b和计算a同理
以计算b为例
设a为斐波那契数列 则b可以拆分为k个斐波那契数的和
而T的个数就是那k个斐波那契数的前一项的和
轻松解决…
代码如下:
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <cstring>
using namespace std;
typedef long long ll;
ll F[10086];
ll T_R;
ll T_L;
int N;
void init_file()
{
freopen("Monkey.in", "r", stdin);
freopen("Monkey.out", "w", stdout);
}
void read_data()
{
F[1] = 1;
F[2] = 1;
for(int i = 3; i <= 100; i++)
F[i] = F[i - 1] + F[i - 2];
scanf("%d", &N);
}
ll cal_R(ll x)
{
ll X = x;
for(int i = 92; i >= 2; i--) //至于为什么是92……打个数列的表它在93爆了…∴是92
{
if (X >= F[i])
{
X -= F[i];
T_R += F[i - 1];
}
}
}
ll cal_L(ll x)
{
ll X = x;
for(int i = 92; i >= 2; i--)
{
if (X >= F[i])
{
X -= F[i];
T_L += F[i - 1];
}
}
}
void work()
{
while(N--)
{
T_L = 0;
T_R = 0;
ll L; ll R;
scanf("%I64d%I64d", &L, &R);
cal_R(R);
cal_L(L - 1);
printf("%I64d\n", T_R - T_L);
}
}
int main()
{
init_file();
read_data();
work();
return 0;
}