Codeforces Round #879 Div.2 참가 후기 및 문제 풀이

A번 문제: 부호 조정을 통한 곱의 양수화

배열에 포함된 정수들 중 -1과 1의 개수를 세어, 전체 원소의 곱이 양수가 되도록 최소 연산 횟수를 구하는 문제이다. 핵심은 음수(-1)의 개수가 홀수일 경우 하나를 제거하고 1로 변환해야 한다는 점이다. 이후 1의 개수가 -1의 개수 이상이 될 때까지 두 개씩 변환해 나간다. 이때 매번 두 개의 -1을 1로 바꾸므로 연산 횟수는 2씩 증가한다.

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

int main() {
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        int neg = 0, pos = 0;
        for (int i = 0; i < n; i++) {
            int x;
            cin >> x;
            if (x == -1) neg++;
            else pos++;
        }

        int ops = 0;
        // 음수 개수가 홀수면 짝수로 만들기
        if (neg % 2 == 1 && neg > 0) {
            neg--;
            pos++;
            ops++;
        }

        // pos가 neg보다 많아질 때까지 -1을 1로 두 개씩 변환
        while (pos < neg) {
            pos += 2;
            neg -= 2;
            ops += 2;
        }

        cout << ops << '\n';
    }
    return 0;
}

B번 문제: 두 문자열로 표현된 수의 차이 최소화

두 매우 큰 수가 문자열 형태로 주어지고, 각 자리에서 숫자를 변경하여 두 수의 차이를 줄이는 문제이다. 실제로 뺄셈을 수행할 필요 없이, 첫 번째로 다른 자리에서 앞선 부분은 각 자릿수 차이의 절댓값을 더하고, 그 이후 자리는 모두 9로 만들어 최대 기여도를 반영한다. 길이가 다르면 짧은 쪽에 앞부분에 0을 추가하여 길이를 맞춘다.

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

void 출력(int128 값) {
    if (값 >= 10) 출력(값 / 10);
    putchar(값 % 10 + '0');
}

int main() {
    int t;
    cin >> t;
    while (t--) {
        string a, b;
        cin >> a >> b;

        if (a == b) {
            cout << 0 << endl;
            continue;
        }

        if (a.length() < b.length()) swap(a, b);
        // 짧은 문자열 앞에 0 삽입
        while (b.length() < a.length()) {
            b = "0" + b;
        }

        int idx = 0;
        while (idx < a.length() && a[idx] == b[idx]) idx++;

        int128 결과 = 0;
        // 일치하는 부분까지는 자릿수 차이 누적
        for (int i = 0; i <= idx; i++) {
            결과 += abs(a[i] - b[i]);
        }
        // 불일치 시작 위치 이후 모든 자리는 9로 간주
        결과 += 9 * (a.length() - idx - 1);

        출력(결과);
        cout << endl;
    }
    return 0;
}

C번 문제: 문자열 변환 게임에서의 최적 전략

Alice와 Bob이 번갈아 가며 문자열을 조작하는 게임이다. Alice는 문자열 s1을, Bob은 s2를 조작하며, 목표는 두 문자열을 일치하게 만드는 것이다. 각 플레이어는 자신의 차례에 접두사를 뒤집고 모든 비트를 반전시킬 수 있다. 해결 핵심은 두 가지 시나리오를 고려하는 것이다:

  • s2를 기준으로 얼마나 많은 위치가 s1과 다른지 확인.
  • s1을 뒤집었을 때 s2와 얼마나 다른지 비교.

각 경우에 대해 필요한 동작 수를 계산하고, Alice가 선공이므로 가능한 최소 값을 선택한다. 차이가 홀수냐 짝수냐에 따라 동작 수가 달라지며, 최종적으로 두 전략 중 작은 값을 출력한다.

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

int main() {
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        string s, t_str;
        cin >> s >> t_str;

        if (s == t_str) {
            cout << 0 << endl;
            continue;
        }

        ll diff_orig = 0, diff_rev = 0;
        for (int i = 0; i < n; i++) {
            if (s[i] != t_str[i]) diff_orig++;
        }

        reverse(s.begin(), s.end());
        for (int i = 0; i < n; i++) {
            if (s[i] != t_str[i]) diff_rev++;
        }

        ll ans = LLONG_MAX;

        // 원본 상태에서의 전략
        if (diff_orig == 1) {
            ans = min(ans, 1LL);
        } else {
            if (diff_orig % 2 == 1) {
                ans = min(ans, 2 * diff_orig - 1);
            } else {
                ans = min(ans, 2 * diff_orig);
            }
        }

        // 뒤집은 상태에서의 전략
        if (diff_rev == 0) {
            ans = min(ans, 2LL);
        } else {
            if (diff_rev % 2 == 0) {
                ans = min(ans, 2 * diff_rev - 1);
            } else {
                ans = min(ans, 2 * diff_rev);
            }
        }

        cout << ans << endl;
    }
    return 0;
}

태그: Codeforces C++ 알고리즘 경연 문자열 처리 게임 이론

6월 25일 21:59에 게시됨