PS 기록/CP

Codeforces Round #851 (Div. 2) 코드포스 첫 도전 후기 + C번 자력솔 [23.02.09]

pearl.k 2023. 2. 11. 15:57

1. 첫 도전 후기

 코드포스에 도전해봐야 겠다고 마음먹은 이유는 바로 백준 사이트에 있다. 백준 랭킹을 보면 닉네임이 Bold + 화려한 색으로 꾸며진 사람들이 있다. 보고 너무 신기하고 멋있어서... 무엇을 하면 저런 닉네임을 받을 수 있지? 궁금증이 생겼다. 그렇게 구글링을 하면서 알아본 결과 외부 사이트의 랭킹, 레이팅을 끌어온 것이라는 걸 알게 됐다.

 처음에 코드포스만 서치에 걸려서 코드포스를 준비해야겠다고 마음 먹었다. (처음 마음먹은 건 1월 중순?) n일에 한 번씩 코드포스 사이트에 들어가서 일정을 확인했다. 사실 쫄보+뉴비+자신감 부족 등등.. 여러 요인으로 인해서 첫 시험으로 div. 3이나 div. 4를 치고 싶었는데 OMG(엄마엄마갓) 내가 코포 도전 결심을 너무 늦게 하는 바람에 쉬운 대회는 이미 없어져버렸다. 꼼짝없이 div. 2 말고 신청할 수 있는게 없었다.

 이후 멘붕이 와서 주변 커뮤니티나 코포 해보신 분들한테 저기...뉴비도 div. 2 봐도 되나요? 이렇게 물어보고 다녔다. 다행이 뉴비도 봐도 된다고 하셨다. 앞에 쉬운 문제가 나오니까 걱정 말라는 응원까지 덤으로 받았다!!! 그래서 큰 맘 먹고 후루룩 신청했다.

 시험이 러시아 시간대에 맞춰져 있어서 밤 늦게 풀어야했다. 야행성이 아닌 나는 카페인을 도핑하고 문제를 풀었는데, 덕분에 밤을 다 새버려서 다음 날 컨디션에 악영향이 갔다. 다음부터 코포는 시간대를 잘 보고 내 체력이 감당할 수 있는 선에서 해야겠다는 생각이 들었다.


2. (시험 후) C번 자력솔 후기

 사실 본 시험 때는 C번 규칙에서 헤메다가 시간을 다 써서 못 풀었다. 마지막에 for문 조작하면서 시간이 다 가버렸다. C번의 가장 큰 실패 요인을 꼽자면, 내가 정확한 규칙을 찾기도 전에 먼저 for문 써놓고 하나씩 조작하면서 풀려고 했던 것이다. 정확한 규칙을 적어놓았으면 구현까지 크게 시간이 걸리지 않았을 것 같다. 근데 내가 실전 경험이 부족해서.. 마음이 급한 나머지 일을 벌여 놓고 수습을 못하게 되어버린 상황.

 시험 끝나고 백준에 문제가 올라오자마자 한 것은 정확한 규칙 찾기다. ***현재 div. 2 #851 라운드의 모든 문제를 백준 사이트에서 확인할 수 있다!! 

https://www.acmicpc.net/problem/27489

 

27489번: Matching Numbers

For the third test case, each integer from $1$ to $6$ appears once. The sums of matched pairs are $4+2=6$, $1+6=7$, and $3+5=8$, which are consecutive and distinct.

www.acmicpc.net

(1) n개의 연속한 자연수의 합이 나올 수 있는지 판단

- 나는 예전에 n개의 연속한 자연수의 합 관련한 문제를 본 적이 있기에 그 내용을 이용해서 판단했다. (관련 내용 링크: https://data-make.tistory.com/307) 이 링크의 3번에 쓰인 내용을 응용하면 이 코드에도 쓸 수 있다.

import sys
T = int(sys.stdin.readline())

for i in range(T):
    n = int(sys.stdin.readline())
    num = [i for i in range(1, 2*n+1)]
    # 1~n 까지의 합
    result = sum(num) - sum(num[0:n])
    
    if (result % n) == 0:
    	print('Yes')
    else:
    	print('No')

 위 코드는 내가 작성한 정답 코드 중 일부이다. result = (1부터 2n까지의 합) - (1부터 n까지의 합) 여기에 result%n == 0을 만족하면 가능하다.

- 다른 분들 풀이를 보니 1~2n까지 쭉 나열해보고 n이 홀수라면 'Yes', n이 짝수라면 'No' 라는 규칙을 발견하여 그냥 처음부터 바로 쓰신 것 같다. (증명을 따로 하지 않고 그냥 n이 홀수 일 때만 계산한 것 같다.)

 

(2) 규칙 찾기

 원소 1~2n 까지 쭉 나열해놓고 서로 매칭을 하다 보면 원소 n을 기준으로, n 이하인 수 중에 홀수, 짝수를 따로 매칭했을 때 원하는 결과가 나온다.

홀수 (배열 내 인덱스로 표현하기 때문에 0부터 시작 한다.)

더보기

(0, 2n-1) (2, 2n-2) (4, 2n-3) ....

홀수 번째 수를 배열 끝에서부터 하나씩 대응해주는 규칙이 있다.

짝수 (배열 내 인덱스로 표현하기 때문에 1부터 시작 한다. 여기서 num[n]은 n+1 이다.)

더보기

(n-2, n) (n-4, n+1), (n-6, n+2) ....

가운데 원소 n을 기준으로 (n의 list 내 index는 n-1) 둘로 나눈다. 원소 n 이하의 짝수와 n 보다 큰 수를 차례대로 하나씩 대응해주는 규칙이 있다.

이 규칙을 바탕으로 내가 구현한 완성 코드는 다음과 같다.

import sys
T = int(sys.stdin.readline())

for i in range(T):
    n = int(sys.stdin.readline())
    num = [i for i in range(1, 2*n+1)]
    result = sum(num) - sum(num[0:n])
    if (result % n) == 0:
        if n == 1:
            print('Yes')
            print(*num)
        else:
            print('Yes')
            for j in range(n//2+1):
                print(num[2*j], num[2*n-1-j])
            for z in range(n//2):
                print(num[n-2*(z+1)], num[n+z])
    else:
        print('No')

 n == 1 일 때 방어코드를 추가하고, 다른 상황에서는 원래대로 돌아가게 만들었다.

 

++ 번외)) 내 풀이 외에도 다른 분들 풀이를 참고하여 다시 도전해봤다.

코드 실행 시간은 다들 비슷했는데, 코드 길이를 내 것의 절반정도로 줄이신 분이 있어서 신기했다.

후기 끝 >.0