Codeforces: Round #708 (Div.2)

2021-03-17

Codeforces

A. Meximization

You are given an integer 𝑛 and an array 𝑎1,𝑎2,,𝑎𝑛. You should reorder the elements of the array 𝑎 in such way that the sum of 𝐌𝐄𝐗 on prefixes (𝑖-th prefix is 𝑎1,𝑎2,,𝑎𝑖) is maximized.

Formally, you should find an array 𝑏1,𝑏2,,𝑏𝑛, such that the sets of elements of arrays 𝑎 and 𝑏 are equal (it is equivalent to array 𝑏 can be found as an array 𝑎 with some reordering of its elements) and 𝑛𝑖=1𝐌𝐄𝐗(𝑏1,𝑏2,,𝑏𝑖) is maximized.

𝐌𝐄𝐗 of a set of nonnegative integers is the minimal nonnegative integer such that it is not in the set.

For example, 𝐌𝐄𝐗(1,2,3)=0, 𝐌𝐄𝐗(0,1,2,4,5)=3.

Input

The first line contains a single integer 𝑡 (1𝑡100) — the number of test cases.

The first line of each test case contains a single integer 𝑛 (1𝑛100).

The second line of each test case contains 𝑛 integers 𝑎1,𝑎2,,𝑎𝑛 (0𝑎𝑖100).

Output

For each test case print an array 𝑏1,𝑏2,,𝑏𝑛 — the optimal reordering of 𝑎1,𝑎2,,𝑎𝑛, so the sum of 𝐌𝐄𝐗 on its prefixes is maximized.

If there exist multiple optimal answers you can find any.

풀이

0 부터 100 까지 배열을 만든 다음 각 숫자에 맞춰 각 숫자가 몇개 있는지 세어준다. 처음엔 순서대로 0 부터 100 까지 돌면서 숫자가 있으면 출력해주고 하나씩 빼준다. 이후엔 남은 숫자 아무거나 출력해도 되므로 남은 순서대로 다 출력해준다.

코드

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

int A[102];
int vst[102];

void solve() {
    int n; cin >> n;
    memset(vst, 0, sizeof(vst));
    for (int i = 0; i < n; i++) {
        cin >> A[i];
        vst[A[i]]++;
    }
    for (int i = 0; i < 101; i++) {
        if (vst[i] > 0) {
            cout << i << " ";
            vst[i]--;
        }
    }
    for (int i = 0; i < 101; i++) {
        while (vst[i] > 0) {
            cout << i << " ";
            vst[i]--;
        }
    }
    cout << "\n";
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t; cin >> t;
    while(t--) solve();
    return 0;
}

B. M-arrays

You are given an array 𝑎1,𝑎2,,𝑎𝑛 consisting of 𝑛 positive integers and a positive integer 𝑚.

You should divide elements of this array into some arrays. You can order the elements in the new arrays as you want.

Let’s call an array 𝑚-divisible if for each two adjacent numbers in the array (two numbers on the positions 𝑖 and 𝑖+1 are called adjacent for each 𝑖) their sum is divisible by 𝑚. An array of one element is 𝑚-divisible.

Find the smallest number of 𝑚-divisible arrays that 𝑎1,𝑎2,,𝑎𝑛 is possible to divide into.

Input

The first line contains a single integer 𝑡 (1𝑡1000) — the number of test cases.

The first line of each test case contains two integers 𝑛,𝑚 (1𝑛105,1𝑚105).

The second line of each test case contains 𝑛integers 𝑎1,𝑎2,,𝑎𝑛 (1𝑎𝑖109).

It is guaranteed that the sum of 𝑛 and the sum of 𝑚 over all test cases do not exceed 105.

Output

For each test case print the answer to the problem.

풀이

m 의 나머지로 된 배열을 만든 다음 각 숫자에 맞춰 A[i] % m에 대해 몇 개 있는지 세어준다. 숫자가 m이면 하나를 만들 수 있으므로 처음에 세어준다. 이후 1 부터 m 까지 돎면서 B[i]와 B[m - i]에서 두 수가 모두 0이 아니라면 cnt를 1 더하주고 두 수를 비교하여 작은 수는 0으로 만들어주고 큰수는 작은수 + 1 만큼 빼준다. 두 수가 같다면 둘 다 0 으로 만들어준다. 이후 남은 숫자들에 대해 cnt를 더해준다.

코드

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

void solve() {
    int n, m; cin >> n >> m;
    vector<int> A(n);
    vector<int> B(m);
    for (int i = 0; i < n; i++) {
        cin >> A[i];
        B[A[i] % m]++;
    }
    if (m == 1) { cout << "1\n"; return; }
    int cnt = (B[0] == 0 ? 0 : 1);
    for (int i = 1; i < m; i++) {
        if (B[i] != 0 && B[m - i] != 0) {
            if (B[i] > B[m - i]) { B[i] -= B[m - i] + 1; B[m - i] = 0; }
            else if (B[i] < B[m - i]) { B[m - i] -= B[i] + 1; B[i] = 0; }
            else { B[i] = 0; B[m - i] = 0; }
            cnt++;
        }
    }
    for (int i = 1; i < m; i++) {
        while (B[i] > 0) {
            B[i]--;
            cnt++;
        }
    }
    cout << cnt << "\n";
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t; cin >> t;
    while(t--) solve();
    return 0;
}

C1. k-LCM (easy version)

It is the easy version of the problem. The only difference is that in this version 𝑘=3.

You are given a positive integer 𝑛. Find 𝑘 positive integers 𝑎1,𝑎2,,𝑎𝑘, such that:

  • 𝑎1+𝑎2++𝑎𝑘=𝑛
  • 𝐿𝐶𝑀(𝑎1,𝑎2,,𝑎𝑘)𝑛2

Here 𝐿𝐶𝑀 is the least common multiple of numbers 𝑎1,𝑎2,,𝑎𝑘.

We can show that for given constraints the answer always exists.

Input

The first line contains a single integer 𝑡 (1𝑡104) — the number of test cases.

The only line of each test case contains two integers 𝑛,𝑘 (3𝑛109,𝑘=3).

Output

For each test case print 𝑘 positive integers 𝑎1,𝑎2,,𝑎𝑘, for which all conditions are satisfied.

풀이

규칙을 찾아서 풀었다.

  • n이 4의 배수이면 {n2,n4,n4} 로 구성할 수 있다.
  • n이 4의 배수가 아닌 짝수면 {n21,n21,2} 로 구성할 수 있다.
  • n이 홀수이면 {n2,n2,1} 로 구성할 수 있다.

코드

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

void solve() {
    int n, k; cin >> n >> k;
    if (n % 4 == 0) cout << n / 2 << " " << n / 4 << " " << n / 4 << "\n";
    else if (n % 2 == 0) cout << n / 2 - 1 << " " << n / 2 - 1 << " " << 2 << "\n";
    else cout << n / 2 << " " << n / 2 << " " << 1 << "\n";
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t; cin >> t;
    while(t--) solve();
    return 0;
}

C2. k-LCM (hard version)

It is the hard version of the problem. The only difference is that in this version 3𝑘𝑛.

You are given a positive integer 𝑛. Find 𝑘 positive integers 𝑎1,𝑎2,,𝑎𝑘, such that:

  • 𝑎1+𝑎2++𝑎𝑘=𝑛
  • 𝐿𝐶𝑀(𝑎1,𝑎2,,𝑎𝑘)𝑛2

Here 𝐿𝐶𝑀 is the least common multiple of numbers 𝑎1,𝑎2,,𝑎𝑘.

We can show that for given constraints the answer always exists.

Input

The first line contains a single integer 𝑡 (1𝑡104) — the number of test cases.

The only line of each test case contains two integers 𝑛,𝑘 (3𝑛109,3𝑘𝑛).

It is guaranteed that the sum of 𝑘 over all test cases does not exceed 105.

Output

For each test case print 𝑘 positive integers 𝑎1,𝑎2,,𝑎𝑘, for which all conditions are satisfied.

풀이

위 규칙에서 응용하면 된다.

먼저 k가 3이 될때까지 1을 출력하면서 n과 k를 줄여준다.

이후 위 규칙과 같이 출력하면 된다.

  • n이 4의 배수이면 {n2,n4,n4} 로 구성할 수 있다.
  • n이 4의 배수가 아닌 짝수면 {n21,n21,2} 로 구성할 수 있다.
  • n이 홀수이면 {n2,n2,1} 로 구성할 수 있다.

코드

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

void solve() {
    int n, k; cin >> n >> k;
    while (k > 3) {
        n--; k--;
        cout << 1 << " ";
    }
    if (n % 4 == 0) cout << n / 2 << " " << n / 4 << " " << n / 4 << "\n";
    else if (n % 2 == 0) cout << n / 2 - 1 << " " << n / 2 - 1 << " " << 2 << "\n";
    else cout << n / 2 << " " << n / 2 << " " << 1 << "\n";
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t; cin >> t;
    while(t--) solve();
    return 0;
}

https://codeforces.com/contest/1497