BD String
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 206 Accepted Submission(s): 92
Problem Description
众所周知,度度熊喜欢的字符只有两个:B和D。
今天,它发明了一种用B和D组成字符串的规则:
S(1)=B
S(2)=BBD
S(3)=BBDBBDD
…
S(n)=S(n−1)+B+reverse(flip(S(n−1))
其中, reverse(s) 指将字符串翻转,比如 reverse(BBD)=DBB , flip(s) 指将字符串中的 B 替换为 D , D 替换为 B ,比如 flip(BBD)=DDB 。
虽然度度熊平常只用它的电脑玩连连看,这丝毫不妨碍这台机器无与伦比的运算速度,目前它已经算出了 S(21000) 的内容,但度度熊毕竟只是只熊,一次读不完这么长的字符串。它现在想知道,这个字符串的第 L 位(从1开始)到第 R 位,含有的 B 的个数是多少?
今天,它发明了一种用B和D组成字符串的规则:
S(1)=B
S(2)=BBD
S(3)=BBDBBDD
…
S(n)=S(n−1)+B+reverse(flip(S(n−1))
其中, reverse(s) 指将字符串翻转,比如 reverse(BBD)=DBB , flip(s) 指将字符串中的 B 替换为 D , D 替换为 B ,比如 flip(BBD)=DDB 。
虽然度度熊平常只用它的电脑玩连连看,这丝毫不妨碍这台机器无与伦比的运算速度,目前它已经算出了 S(21000) 的内容,但度度熊毕竟只是只熊,一次读不完这么长的字符串。它现在想知道,这个字符串的第 L 位(从1开始)到第 R 位,含有的 B 的个数是多少?
Input
第一行一个整数
T
,表示
T(1≤T≤1000)
组数据。
每组数据包含两个数 L 和 R(1≤L≤R≤1018) 。
每组数据包含两个数 L 和 R(1≤L≤R≤1018) 。
Output
对于每组数据,输出
S(21000)
表示的字符串的第
L
位到第
R
位中
B
的个数。
Sample Input
3 1 3 1 7 4 8
Sample Output
2 4 3
只需要知道到某个下标之前的所有B的个数就可以了.显然答案就是a+1+b,这个
a表示前面最长的完整的序列,然后b就是由a串后面|b|长度翻转加变化得到的,
答案就是a中B的个数+1+b中D的个数=a-b+1+|b|(因为a后面长度为|b|的串的BD值
都需要统计,相当于|b|).
这样就把a的规模缩小了,然后继续搜索下去.
#include <cstring>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
#include <queue>
#include <set>
using namespace std;
#define maxn 1111
#define Max 1e18
int cnt;
unsigned long long len[maxn], s[maxn];
unsigned long long f (unsigned long long a) {//b的个数
if (a == 1)
return 1;
if (a == 0)
return 0;
unsigned long long ans = 0;
for (int i = 0; i < cnt; i++) {
if (len[i+1] == a)
return s[i+1];
else if (len[i+1] < a) {}
else {
ans += s[i];
if (len[i] == a)
return ans;
else
return a-len[i]-1 +1+ f (len[i]-(a-len[i]-1));
}
}
}
int main () {
//freopen ("in.txt", "r", stdin);
len[1] = 1, s[1] = 1;
cnt = 1;
for (int i = 2; ; i++) {
len[i] = len[i-1]*2+1;
s[i] = 1+len[i-1];
cnt++;
if (len[i] > Max)
break;
}
int t;
scanf ("%d", &t);
while (t--) {
unsigned long long L, R;
scanf ("%I64d%I64d", &L, &R);
printf ("%I64d\n", f (R) - f (L-1));
}
return 0;
}