PS

BOJ 31422 : AND, OR, XOR 2

lickelon 2024. 2. 18. 23:46
 

31422번: AND, OR, XOR 2

음이 아닌 정수로 이루어진 길이 $N$의 수열 $A_1, A_2, \cdots, A_N$이 주어진다. $\land, \lor, \oplus$를 각각 Bitwise AND, OR, XOR 연산자로 정의하자. 다음 세 값을 $998\,244\,353$으로 나눈 나머지를 각각 구하여

www.acmicpc.net


코드

#include <bits/stdc++.h>

#define all(x) (x).begin(), (x).end()

#define INF 0x7FFFFFFF

using namespace std;

using ll = long long;
using ld = long double;
using pii = pair<int,int>;
using pll = pair<ll, ll>;

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    int n;
    cin >> n;
    ll arrA[32] = {};
    ll arrB[32] = {};
    ll arrC[32] = {};
    ll ansA = 0;
    ll ansB = 0;
    ll ansC = 0;
    for(int i = 0; i < n; i++) {
        int input;
        cin >> input;
        for(int j = 0; j < 32; j++) {
            int t = (input >> j) & 1;
            if(t) {
                arrA[j] += 1;
                ansA += (arrA[j] << j) % 998244353;
                ansA %= 998244353;
                arrB[j] = i + 1;
                ansB += (arrB[j] << j) % 998244353;
                ansB %= 998244353;
                arrC[j] = i + 1 - arrC[j];
                ansC += (arrC[j] << j) % 998244353;
                ansC %= 998244353;
            }
            else {
                arrA[j] = 0;
                ansB += (arrB[j] << j) % 998244353;
                ansB %= 998244353;
                ansC += (arrC[j] << j) % 998244353;
                ansC %= 998244353;
            }
        }
    }
    cout << ansA << " " << ansB << " " << ansC;

    return 0;
}

풀이

K번째 원소를 처리할 때, $\sum\limits_{i=1}^{K}{( A_i @ ...  @ A_K )}$를 처리한다. (@는 연산자)

위의 수열의 합을 효과적으로 처리하기 위해 비트별로 수열에 포함된 1의 수를 저장한다.

이제 비트별로 해당 위치의 값에 따라 1의 수가 어떻게 변하는지를 구해준다. DP식은 다음과 같다.

$$AND(K) = \begin{cases}AND(K-1)+1, & \mbox{if bit is }1\\0, & \mbox{if bit is }0\\ \end{cases}$$

$$OR(K) = \begin{cases}K+1, & \mbox{if bit is } 1\\OR(K-1), & \mbox{if bit is } 0\\ \end{cases}$$

$$XOR(K) = \begin{cases}K+1-XOR(K-1), & \mbox{if bit is } 1\\ XOR(K-1), & \mbox{if bit is } 0 \\ \end{cases}$$

비트의 위치에 따라 적절한 2의 제곱수를 곱해주고 더해주면 된다.

728x90