처음 음식의 맛 0,1이 n개 주어지고 쿼리가 q개 주어진다.


쿼리는 i,j로 구성되어 있으며 [i:j] (i,j를 포함하는 구간)을 최대의 맛을 얻을 수 있도록 먹었을 때의 값을 출력해야 한다.


음식의 순서는 범위 내에서 임의로 정할 수 있으며 음식을 먹으면 먹은 맛만큼의 값이 구간의 음식에 전부 더해진다


1 1 0 1 을 왼쪽에서부터 순서대로 먹는다고 하면


_ 2 1 2 -> _ _ 3 4 -> _ _ _ 7 -> _ _ _ _ = 13 의 결과가 나온다.


잘 보면 처음 먹은 1은 8 = 2^3 번 더해지고 두번째로 먹은 1은 4 = 2^2 번 더해진다.


마지막으로 먹은 1은 한번만 더해지므로 1은 무조건 먼저 먹는게 이득이라는 것을 알 수 있다.


식을 알기위해 11100을 계산해보자


2^4 + 2^3 + 2^2 가 나온다.


2^(구간길이-1) 부터 1의 갯수번 더한다.


따라서 식은 (2^l - 1) - (2^cnt(0) - 1) = 2^l - 2^cnt(0) 이 된다.


쿼리가 10만개이므로 빠르게 처리하기 위해서 2^100000까지 배열에 미리 다 저장하고 1의 개수를 구간합을 통해 O(1)만에 구한다.


#include <iostream>
using namespace std;
 
typedef long long ll;
 
ll n, q, c[100111], d[100111];
const ll mod = 1000000007;
char a[100111];
 
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    cin >> n >> q >> a + 1;
    d[0= 1;
    for (int i = 1; i <= n; ++i) 
        d[i] = (d[i - 1* 2) % mod;
    for (ll i = 1; i <= n; ++i) 
        c[i] = c[i - 1+ (a[i] == '1');
    while (q--) {
        ll u, v;
        cin >> u >> v;
        ll zeros = v - u + 1 - (c[v] - c[u - 1]);
        cout << (d[v - u + 1- d[zeros] + mod) % mod << '\n';
    }
    return 0;
}
cs


'codeforces > #520 div2' 카테고리의 다른 글

D. Fun with Integers  (0) 2018.11.17
B. Math  (0) 2018.11.17
A. A Prank  (0) 2018.11.17

+ Recent posts