Codeforces: Round #708 (Div.2)
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의 배수가 아닌 짝수면 {n2−1,n2−1,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의 배수가 아닌 짝수면 {n2−1,n2−1,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;
}