CP

[CF] Codeforces Round 901 (Div. 2)

yunny_world 2023. 10. 3. 02:25

https://codeforces.com/contest/1875

 

Dashboard - Codeforces Round 901 (Div. 2) - Codeforces

 

codeforces.com

그린 행동을 해버렸다. 1시간 반 가까이 C를 못 풀어서 멘탈이 나가서 탈주해 버렸다. 라운드 치고 화가 잔뜩 나서 산책 좀 하다가 집에 돌아와서 C, D 업솔빙을 하고 잤다.
솔직히 이럴 때 빠르게 D를 보고 멘탈 관리를 했어야 하는데, 판단을 잘못했다.
요즘 코포를 너무 못해서 위기감을 느끼며 평소에 안 하던 업솔빙도 하고 글도 쓴다.
 

A. Jellyfish and Undertale (00:09)

tool은 타이머가 1일 때 쓰는 게 항상 최적이라는 점을 이용하면 된다.
 

B. Jellyfish and Game (00.30)

$a_i, b_i$의 최대 최소를 누가 가지고 있는 지 4가지 상태로 나타낸 뒤에 최적으로 시행을 해보자.
첫 라운드 종료 시에 항상 Jellyfish가 최대, Gellyfish가 최소를 가지게 된다.
이 상태에서 라운드를 계속 진행하면, Jellyfish가 최대, Gellyfish가 최소를 가지는 상태와 Jellyfish가 최소, Gellyfish가 최대를 가지는 상태가 번갈아 나타나게 된다.
첫 라운드만 직접 해주고, 나머지는 기우성에 따라 처리해주면 된다.
 

C. Jellyfish and Green Apple (Upsolved)

최적으로 나누었을 때 한 사람이 가지게 될 사과 조각이 어떠한 비트에 대응된다는 사실은 직접 써보면 알 수 있다.
나는 대회 내내 여기서 진전이 없었다. 
반으로 자르는 횟수를 구해야 하는데, 이 방식을 쉽게 처리할 방식을 찾지 못했다. 
여기서부터는 크게 2가지 방법이 있다.
 
풀이1. 조각의 개수 관리하기

void solve(void) {
  int n, m; cin >> n >> m;
  n %= m;
 
  long long ans = 0;
  int cnt = 0;
  while (n != 0) {
    ans += n;
    n *= 2;
    n %= m;
    cnt++;
    if (cnt > 1000) {
      ans = -1;
      break;
    }
  }
  cout << ans << "\n";
}

 현재 조각을 모두 자르면 조각의 개수가 2배가 되고, 이를 정확히 m명에게 나눠주어야 한다는 사실을 이용한 풀이이다.
while문을 한 번 돌 때마다, n번 자르고 나눠줄 수 있는 걸 나눠주면 n%m개의 조각이 남는다.
우리 학회 1학년 친구의 코드이다. 멋지다.
 
풀이2. 조각의 개수 계산하기

ll n, m;
 
void solve()
{
	cin >> n >> m;
	n %= m;
	ll g = gcd(n, m);
	ll a = n / g, b = m / g;
 
	if (__builtin_popcount(b) > 1) cout << "-1\n";
	else cout << 1ll * __builtin_popcount(a) * m - n << '\n';
}

1번 자르면 조각의 개수가 1개 늘어난다는 점을 이용한 풀이이다. 결과적으로 남은 조각의 개수로부터 역추적하는 느낌이다.
결국 한 사람이 갖게 될 조각의 개수가 __builtin_popcount(a)이고 m명이 있으므로, 결과적으로 남은 조각의 개수는 둘을 곱한 것이다. 처음에 1개의 조각이 있던 것이 아니라, n개의 조각이 있었으므로 여기서 n을 빼면 답이 된다.
 
두 풀이 모두 조각의 개수에 대해 생각하는 것이 관건이었는데, 나는 조각의 크기와 개수를 동시에 생각하려고만 해서 못 풀었던 것 같다. 개수만 고려해도 저절로 크기도 맞춰진다는 점을 생각해 풀었어야 할 것 같다. 
 
이 풀이가 에디토리얼에 소개된 풀이인데, 마지막 식이 너무 이해가 안 되어서 질문을 했는데, 누군가가 친절하게 답해줘서 너무 기뻤다...
 

상황적으로 이해하려면 전자를, 식으로 받아들이려면 후자를 보면 될 것 같다.
 

D. Jellyfish and Mex (Upsolved)

  • mex값을 계속해서 줄여나가면서 원소를 제거해야 하므로, $a_i$가 큰 것부터 제거해야 한다.
  • $a_i$값이 동일한 것들이 여러 개 있으면, 연속적으로 전부 제거해야 한다.

위 두 가지 관찰을 이용해서 $a_i$ 내림차순으로 정렬해놓고, $O(n^2)$ dp를 하면 된다.
 
 
아이디어보다 관찰을 먼저 하자.
어려운 걸 풀자.
업솔빙을 하자.
오래 고민한답시고, 답 안보고 문제 던져놓지 말자.
그냥 빠르게 답보고 배우자.

'CP' 카테고리의 다른 글

[CF] Codeforces Round 913 (Div. 3)  (2) 2023.12.06
[AtCoder] AtCoder Beginner Contest 312  (0) 2023.07.30
[AtCoder] AtCoder Beginner Contest 309  (2) 2023.07.08
[CF] Codeforces Round 883 (Div. 3)  (0) 2023.07.08
[CF] Codeforces Round #821 (Div. 2)  (4) 2022.09.23