[英]Range queries on a binary string?
Binary-Decimal二进制-十进制
We are given a binary string S of length n , in which each character is either '1' or '0' .我们得到一个长度为 n的二进制字符串S ,其中每个字符都是'1' 或 '0' 。
And we are asked to perform several queries on the string.我们被要求对字符串执行几个查询。
In each query we are given integers L and R .在每个查询中,我们都给出了整数L和R 。 And we have to tell the value of sub-string S[l..r] , in decimal representation .
我们必须告诉子串S[l..r] 的值,以十进制表示。
Sample testcase:示例测试用例:
Input:
1011 (string S)
5 (number of queries)
1 1 (l, r)
2 2
1 2
2 4
1 4
Output:
1 (1 * 2^0 == 1)
0
2
3 (0 * 2^2 + 1 * 2^1 + 1 * 2^0)
11 (1 * 2^3 + 0 * 2^2 + 1 * 2^1 + 1 * 2^0 = 11)
Constraints约束
1 < N < 10^5
1 < Q < 10^5
As the number can be very large, we are required to print it modulo 10^9 + 7.由于数字可能非常大,我们需要以10^9 + 7 的模数打印它。
Approach方法
So basically we need to convert binary representation sub-string S[l..r] in it's decimal.所以基本上我们需要将二进制表示子字符串 S[l..r] 转换为十进制。
I pre-computed the results of S[i...n-1] for all i:[0, n-1] in array B .我预先计算了数组 B 中所有i:[0, n-1]的S[i...n-1]的结果。 So now B[i] represents the decimal number representation of sub-string S[i..n-1] .
所以现在B[i]表示子串S[i..n-1]的十进制数表示。
vector<int> pow(1e5, 1);
for(int i = 1; i < 1e5; i++) {
pow[i] = (pow[i - 1] * 2) % mod;
}
string s;
getline(cin, s);
vector<int> B(n, 0);
int prev = 0;
for(int i = 0; i < n; i++) {
B[(n - 1) - i] = (prev + (s[(n - 1) - i] == '1' ? pow[i] : 0)) % mod;
prev = B[(n - 1) - i];
}
while(q--) {
int l, r;
cin >> l >> r;
cout << ((B[l] - (r + 1 < n ? B[r + 1] : 0) + mod) % mod) / pow[n - (r + 1)]<< "\n";
}
return 0;
With the above approach only sample testcase got passed and all other cases are giving the wrong answers(WA) .使用上述方法,只有示例测试用例通过了,所有其他情况都给出了错误的答案(WA) 。
I even tried using Segment tree for this problem but that is also not working.我什至尝试使用段树来解决这个问题,但这也不起作用。
What is the correct approach to solve this problem ?
解决这个问题的正确方法是什么?
Define V[k]
to be the value of the digits of S
starting with the k
th one.定义
V[k]
为S
从第k
位开始的数字的值。
Then the value of the substring S[l..r] = (V[l] - V[r+1]) / 2^(n - r - 1)
.然后子串的值
S[l..r] = (V[l] - V[r+1]) / 2^(n - r - 1)
。 (Something like that, I may have an off by one error. Play with small examples.) (类似的事情,我可能会犯一个错误。玩小例子。)
Now the useful fact about 10^9 + 7
is that it is a prime.现在关于
10^9 + 7
的有用事实是它是素数。 (The first 10 digit prime.) Which means that dividing by 2 is the same as multiplying by 2^(10^9 + 5)
. (前 10 位素数。)这意味着除以 2 与乘以
2^(10^9 + 5)
。 Which is a constant that you can figure out with repeated squaring.这是一个常数,您可以通过重复平方计算得出。 And raising that constant to a high power can be done very efficiently using repeated squaring.
使用重复平方可以非常有效地将该常数提高到一个高次幂。
With this you can create a lookup table for V
, and then do your queries in time O(log(n))
.有了这个,您可以为
V
创建一个查找表,然后在O(log(n))
时间内进行查询。
This seems the same as regular sum range-queries, except (1) we need to store the partial sums mod 10^9 + 7, (2) during retrieval, we need to "shift" the relevant sections of the full sum by the length of the sections on their right.这似乎与常规和范围查询相同,除了(1)我们需要存储部分和 mod 10^9 + 7,(2)在检索期间,我们需要通过右边部分的长度。 To "shift" in this case would mean multiplying by 2^(length_of_suffix) mod 10^9 + 7. And of course sum the sections mod 10^9 + 7.
在这种情况下,“移位”意味着乘以 2^(length_of_suffix) mod 10^9 + 7。当然,对部分 mod 10^9 + 7 求和。
But btilly's answer seems much simpler :)但是 btilly 的答案似乎要简单得多:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.