PS/코드포스, 앳코더 후기

Codeforces Round 1004 후기

notkim16 2025. 2. 12. 15:42

어제 코포에서 다시 한번 2600플마단 퍼포먼스를 받고 레이팅을 2380까지 올렸다.

 

0:00

A번을 잡았다. 인터랙티브여서 탈주하고 싶었는데 일단 문제를 읽고 생각해보기로 했다.

문제 읽으니까 바로 풀이가 나왔다.

풀이

더보기

x_i가 모두 다른 경우에는 x_i = 1인 i를 a, x_i = n인 i를 b라고 했을 때

? a b

? b a

를 출력하고 두 결과가 모두 n-1 이상이라면 B, 아니면 A

 

x_i 중 같은 것이 있는 경우에는 모든 i에 대해서 x_i != j인 j 가 존재한다.

? j ( j%n+1)

을 출력하고 0이면 A, 아니면 B

 

최대 두 번의 쿼리로 A/B를 구분할 수 있다.

 

물음표 하나 빼먹어서 프리텟 1에서 틀리는 소란이 있었지만 암튼 0:15에 AC를 받았다.

0:15

B번을 잡았다.

일단 아래 관찰은 자명하게 할 수 있다.

관찰 1

더보기

* 모든 i에 대해서 a_i >= mex(a_{i+1}, ...., a_n)을 만족시키기만 하면 된다.

* 우변의 mex값은 n을 초과하지 않는다.

위 관찰을 바탕으로 풀이를 냈다.

풀이 1

더보기

오른쪽에서 왼쪽으로 순회하며, a_i < n인 경우와 a_i >= n인 경우로 나눈다.

전자의 경우 mex <= a_i일 때에만 a_i를 부분수열에 넣어주고 mex값을 업데이트한다.

후자의 경우 a_i를 부분수열에 넣는다.

 

4

0 1 0 1

을 입력하면 2가 나오는 풀이다.

예제에서 틀려서 몇 가지 관찰을 더 하고 풀이를 냈다.

관찰 2

더보기

* 0은 최대 1개만 포함될 수 있다.

* 가장 왼쪽에 있는 0 1개만 포함하는 것이 가장 이득이다.

풀이 2

더보기

0을 0개 쓰는 경우와 1개 쓰는 경우로 나눈다.

전자의 경우에는 0이 아닌 모든 원소들을 부분수열에 포함시켜 개수를 센다.

후자의 경우에는 풀이 1대로 하는데, a_i = 0인 경우에만 가장 왼쪽에 있는 0이 포함되도록 따로 처리해준다.

 

두 방법으로 얻은 부분수열의 크기의 최댓값을 출력한다.

 

이 풀이로 AC를 받았다.

0:33

C번을 잡았다.

한 5분정도 생각하고 다음 관찰을 했다. (스포: 틀린 관찰임)

관찰 1

더보기

i번 시행까지 했고, 두 수가 같고 하나만 다른 경우, 예를 들어 P = Q라고 하자.

P의 값은 일정하다.

풀이 1

더보기

dp0[i]: i번 시행까지 했을 때 세 수가 모두 같은 경우의 수

dp1[i]: i번 시행까지 했을 때 두 수만 같은 경우의 수

관찰 1에 의해 두 수 (wlog P, Q)가 같다고 하면, P^R의 값은 일정하다.

P^R = a[i+1]이면 dp0[i+1] = dp1[i] / dp1[i+1] = dp0[i]*3 + dp1[i]*2

아니면 dp1[i+1]=dp1[i]

예제에서 틀려서 디버깅을 하다가 관찰 1이 잘못되었음을 알아냈다.

3

1 1 2

가 주어진 경우 PPR / PQR 순서로 시행을 하면 두 경우 모두 P = Q이지만, 전자에서 P = 0, 후자에서 P = 1이다.

위 예제를 어떻게 처리할지 생각하다가 다음 관찰을 했다.

관찰 2

더보기

* i번 시행까지 했을 때 P^Q^R의 값은 일정하다.

* 즉 P = Q이면, R의 값은 일정하다.

* P = Q일 때, P ^ a[i+1] = R이면 "같은 두 수의 값"이 달라질 수 있다. (P => P ^ a[i+1] or P로 분기점이 된다.)

* 위 식을 만족하는 P는 유일하므로 "같은 두 수의 값"은 최대 n가지 존재한다. 그리고 "같은 두 수의 값"을 인덱스로 하는 dp 배열을 만들면 한 번의 시행마다 O(1)개의 원소를 조작한다.

풀이 2

더보기

dp[i]: "같은 두 수의 값"이 i인 경우의 수

b[i]: i번 시행까지 했을 때 세 수의 값이 같은 경우의 수

a[i]들의 누적 xor을 x라는 변수에 저장하자.

i번째 연산을 할 때, x = a[1] ^ ... ^ a[i]이다.

b[i] = dp[x], dp[x^a[i]] = b[i-1] * 3 + dp[x]  * 2, dp[x] = 0을 i = 1~n까지 한다.

b[n]과 모든 dp값들을 합친 것이 답이다.

같은 두 수의 값이 2^30-1까지 갈 수 있는데, map을 사용해서 해결했다.

C번에서 처음에 풀이를 잘못 냈고 수정하는데 시간이 걸려서 1:19에 AC를 받았다.

1:19

D1번을 잡았다.

10분정도 생각하고 다음 관찰을 했다.

관찰

더보기

* c개의 비행기를 n층에서 던져야 한다.

* 0~c개의 비행기를 n-1층에서 던지는데, n층에서 던진 것들과 합쳤을 때 c번째 이후로는 n-1층에서 던질 수 없다.

* 0~c개의 비행기를 n-2층에서 던지는데, 위에 층들과 합쳤을 때 c번째 이후로는 n-2층에서 던질 수 없다.

...

풀이

더보기

dp[i][j]를 n층부터 시작해서 j층까지 비행기를 던졌을 때, 총 i개의 비행기를 던진 경우의 수라고 하자.

초깃값: dp[c][n]=1

점화식: dp[i][j] = dp[i-c][j+1] * cCc + dp[i-(c-1)][j+1] * cC(c-1) + ... + dp[i-0][j+1] * cC0

구하고자 하는 값: dp[m][1]

c <= 100이므로 nCr 값들은 전처리하면 되고, O(nmc)에 도니까 시간 내에 해결할 수 있다.

한 번에 맞는 관찰을 해서 그런가 C번보다 훨씬 쉬웠다.

1:39

D2를 잡으려고 시도했다.

D1에서 내가 발상한 풀이가 아예 통하지 않다고 생각해서 새로운 풀이를 발상해야 했는데, 20분 내에 발상 -> 구현까지 도저히 할 수 없을 것 같아 GG쳤다. (나중에 들어보니까 D1 풀이를 조금만 변형하면 된다고 하는데 잘 이해하진 못했다.)

2:00 (끝)

사람들 의견이랑 걸린 시간을 보니 A~D1까지 난이도는 모두 골상위~플하위 정도로 비슷했던 것 같다. 결국 A~D1을 빨리 쓱싹하면 점수가 오르는 라운드였다. 나는 C에서 조금 말리긴 했는데 ABD1을 모두 0틀 20분컷해서 퍼포먼스 2600플마단에 합류했다. 라운드 구조가 웬만한 플레하위까지 스피드포스가 되는 나한테 유리해서 퍼포가 잘 나온 것 같다.

방학 시작할 때 개강 전까지 레드를 찍겠다고 다짐했었다. 일주일에 세번씩 팀셋 혼자서 돌기도 하고, 다이아1 찍는다고 하루에 10시간씩 앉아서 PS만 하기도 했었다. 19점 차이로 레드를 찍지는 못했지만 최근 두 번의 라운드에서 레드를 충분히 갈 수 있다는걸 쇼앤프루브 했다. 

앞으로 목표는

* 다음 코포에서 레드 가기

* 플레 중상위를 코포에서 꾸준히 풀어내기

* 5시간 셋이면 플레를 혼자서 다 밀수 있게 하기

정도이다.

 

'PS > 코드포스, 앳코더 후기' 카테고리의 다른 글

코드포스 후기 (2월 4주차)  (0) 2026.03.01
코드포스 후기 (2월 2주차)  (0) 2026.02.16
코드포스 후기 (2월 1주차)  (0) 2026.02.08
12월 30일, 31일 PS 일기  (0) 2025.12.31
Codeforces Round 1001 후기  (0) 2025.01.27