ABC356 대회 문제 해설 및 풀이 코드

A

주어진 범위 1부터 n까지의 수열에서 l부터 r까지의 부분만 뒤집어 출력하는 문제다. 즉, 1부터 l-1까지는 순서대로, l부터 r까지는 역순으로, r+1부터 n까지는 다시 순서대로 출력하면 된다.

#include <bits/stdc++.h>
using namespace std;

int n, L, R;

int main() {
    cin >> n >> L >> R;
    for (int i = 1; i < L; i++) cout << i << " ";
    for (int i = R; i >= L; i--) cout << i << " ";
    for (int i = R + 1; i <= n; i++) cout << i << " ";
    return 0;
}

B

N일 동안 각 영양소의 섭취량을 누적 합산한 후, 목표 섭취량 a_i와 비교한다. 만약 어떤 영양소라도 누적 섭취량이 목표치보다 작으면 "No", 모두 충족하면 "Yes"를 출력한다.

#include <bits/stdc++.h>
using namespace std;

int n, m;
int need[105];
int total[105];

int main() {
    cin >> n >> m;
    for (int i = 1; i <= m; i++) cin >> need[i];
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int val;
            cin >> val;
            total[j] += val;
        }
    }
    for (int i = 1; i <= m; i++) {
        if (need[i] > total[i]) {
            cout << "No";
            return 0;
        }
    }
    cout << "Yes";
    return 0;
}

C

N개의 열쇠 각각을 사용(1)하거나 사용하지 않는(0) 모든 조합을 DFS로 탐색한다.
각 조합에 대해 M개의 테스트 조건을 검사한다: 각 조건에서 명시된 열쇠 중 실제 사용한 열쇠의 개수가 K개 이상일 때 결과가 'o'여야 하고, 미만일 때 'x'여야 한다. 조건을 모두 만족하는 조합의 개수를 센다.

#include <bits/stdc++.h>
using namespace std;

int N, M, K;
int cnt[105];
int keys[105][25];
char res[105];
int used[25];
int answer;

void dfs(int idx) {
    if (idx > N) {
        for (int i = 1; i <= M; i++) {
            int on = 0;
            for (int j = 1; j <= cnt[i]; j++) {
                if (used[keys[i][j]] == 1) on++;
            }
            if ((on >= K && res[i] == 'x') || (on < K && res[i] == 'o'))
                return;
        }
        answer++;
        return;
    }
    used[idx] = 0;
    dfs(idx + 1);
    used[idx] = 1;
    dfs(idx + 1);
}

int main() {
    cin >> N >> M >> K;
    for (int i = 1; i <= M; i++) {
        cin >> cnt[i];
        for (int j = 1; j <= cnt[i]; j++) cin >> keys[i][j];
        cin >> res[i];
    }
    dfs(1);
    cout << answer;
    return 0;
}

D

M을 이진수로 변환한 후, 각 비트 위치 i(0부터 시작)에 대해 0부터 N까지의 숫자 중 i번째 비트가 1인 개수를 누적한다.
비트 i는 2i개의 0과 2i개의 1이 반복되는 패턴을 가지므로, (N+1)을 주기 2i+1로 나누어 몫과 나머지를 이용해 계산한다. M의 i번째 비트가 1일 때만 해당 개수를 합산하며, 결과를 998244353으로 나눈 나머지를 출력한다.

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 998244353;

int main() {
    ll N, M;
    cin >> N >> M;
    
    ll ans = 0;
    for (ll i = 0; (1LL << i) <= M; i++) {
        if (!((M >> i) & 1LL)) continue;
        ll period = 1LL << (i + 1);
        ll full = (N + 1) / period;
        ll rem = (N + 1) % period;
        ans = (ans + full % MOD * ((1LL << i) % MOD)) % MOD;
        if (rem > (1LL << i))
            ans = (ans + (rem - (1LL << i))) % MOD;
    }
    cout << ans;
    return 0;
}

태그: AtCoder ABC356 dfs 비트마스크 구현

7월 19일 20:14에 게시됨