Algorithm/코드포스

Codeforces Global Round 21 1684 → 1665

Edyy 2022. 6. 26. 15:54

https://codeforces.com/contest/1696

 

Dashboard - Codeforces Global Round 21 - Codeforces

 

codeforces.com

!!!! 모든 답은 제 풀이일 뿐 공부를 위한 올바른 정해가 아닐 수 있습니다 !!!!

 

A. NIT orz!

https://codeforces.com/contest/1696/problem/A

 

Problem - A - Codeforces

 

codeforces.com

문제

n길이의 배열 a와 z가 주어진다. 아래의 operation을 원하는 만큼 할 수 있을 때 배열의 원소가 가질 수 있는 최대 값을 출력하는 문제
- 한개의 원소를 골라서 a[i] = (a[i] | z) , z = (a[i] & z) 로 set 한다.
 

 

풀이

 

z는 and 연산을 시킬 수록 값이 작아지니 최대 한번을 or 시킬 원소를 모두 비교해보고 최대 값을 출력해준다.

 

코드

 

    #include <bits/stdc++.h>
    using namespace std;
    long long a[2001];
    int main() {
        ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
        int T;
        cin >> T;
        while (T--) {
            long long n, z;
            cin >> n>>z;
            long long ans = 0;
            for (int i = 1; i <= n; i++) {
                cin >> a[i];
                ans = max(ans, (a[i] | z));
            }
            cout << ans << '\n';
        }
    }

 

B. NIT Destroys the Universe

https://codeforces.com/contest/1696/problem/B

 

Problem - B - Codeforces

 

codeforces.com

문제

 

n길이의 배열 a가 주어진다 . 아래의 operation을 원하는 만큼 할 수 있을 때 모든 원소를 0으로 만들 기 위한 최소 operation의 수를 출력하는 문제

- l과 r을 골라 그 사이에 해당하는 인덱스를 mex(a[l]...a[r])의 값으로 바꾼다.

 

풀이

 

최대 opertaion의 수는 2개이다. 0이 아닌 덩어리의 개수를 세주고 둘중 작은값을 출력해주면 된다.

 

코드

 

    #include <bits/stdc++.h>
    using namespace std;
    long long a[100001];
    int main() {
        ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
        int T;
        cin >> T;
        while (T--) {
            int n;
            cin >> n;
            for (int i = 0; i < n; i++) {
                cin >> a[i];
            }
            int ans = 0;
            for (int i = 0; i < n; i++) {
                if (a[i]) {
                    int i2 = i + 1;
                    while (i2 < n) {
                        if (a[i2])i2++;
                        else break;
                    }
                    i = i2 - 1;
                    ans++;
                }
            }
            cout << min(ans,2) << '\n';
        }
    }

C. Fishingprince Plays With Array

https://codeforces.com/contest/1696/problem/C

 

Problem - C - Codeforces

 

codeforces.com

문제

 

n길이의 배열 a와 k길이의 배열 b와 m이 주어진다. 2개의 operation이 있고 한번의 1개의 opertion을 골라 a에 원하는 만큼 수행할 수 있을 때 a배열을 b와 똑같이 만들 수 있다면 Yes를 아니라면 No를 출력하는 문제

-  m으로 나뉘는 a[i]를 골라서 m개의 a[i]/m 으로 분해한다

-  m개의  연속된 같은 숫자가 있다면 m개의 원소를 a[i]*m으로 합친다.

 

풀이

 

b를 분해하는 opertion도 순서가 변하지 않기 때문에 사실상 가능하다. 둘중 큰 원소를 쪼개주면서 하는 방향으로 계산해주면 된다.

 

코드

    #include <bits/stdc++.h>
    using namespace std;
    long long a[50001];
    long long b[50001];
    stack<pair<long long,long long>> ast, bst;
    int main() {
        ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
        int T;
        cin >> T;
        while (T--) {
            while (!ast.empty())ast.pop();
            while (!bst.empty())bst.pop();
            long long n, m;
            cin >> n >> m;
            for (int i = 0; i < n; i++)cin >> a[i];
            long long k;
            cin >> k;
            for (int i = 0; i < k; i++)cin >> b[i];
            bool flag = true;
            for (int i = n - 1; i >= 0; i--)ast.push({ a[i],1 });
            for (int i = k - 1; i >= 0; i--)bst.push({ b[i],1 });
            while (!ast.empty() && !bst.empty()) {
                long long a = ast.top().first, b = bst.top().first;
                long long as = ast.top().second, bs = bst.top().second;
                //cout << a << ' ' << b << '\n';
                if (a == b) {
                    ast.pop(); bst.pop();
                    long long MIN = min(as, bs);
                    as -= MIN; bs -= MIN;
                    if (as != 0)ast.push({ a,as });
                    if (bs != 0)bst.push({ b,bs });
                }
                else if (a > b) {
                    ast.pop();
                    if (as != 1)ast.push({ a,as - 1 });
                    long long a2 = a;
                    bool tflag = false;
                    while (a2 % m == 0) {
                        a2 /= m;
                        if (a2 == b) {
                            tflag = true;
                        }
                        if (a2 <= b)break;
                    }
                    if (tflag == false) {
                        flag = false;
                        break;
                    }
     
                    a2 = a;
                    while (a2 % m == 0) {
                        a2 /= m;
                        ast.push({ a2,m - 1 });
                        if (a2 == b)break;
                    }
                    bst.pop();
                    if (bs != 1)bst.push({ b,bs - 1 });
                }
                else {
                    bst.pop();
                    if (bs != 1)bst.push({ b,bs - 1 });
                    long long b2 = b;
                    bool tflag = false;
                    while (b2 % m == 0) {
                        b2 /= m;
                        if (b2 == a) {
                            tflag = true;
                        }
                        if (b2 <= a)break;
                    }
                    if (tflag == false) {
                        flag = false;
                        break;
                    }
                    b2 = b;
                    while (b2 % m == 0) {
                        b2 /= m;
                        bst.push({ b2,m - 1 });
                        if (b2 == a)break;
                    }
                    ast.pop();
                    if (as != 1)ast.push({ a,as - 1 });
                }
            }
            if (ast.size() || bst.size())flag = false;
            if (flag)cout << "Yes\n";
            else cout << "No\n";
        }
    }

 

 

자세한 설명에 중점을 두기보다는 대회 기록에 중점을 둔 글입니다 !

틀린 부분은 감사히 지적받겠습니다.