Codeforces Round #792 (Div. 1 + Div. 2)

3Juhwan·2022년 5월 20일
0

Codeforces

목록 보기
2/24

AB 무난하게 풀고 C가 좀 오래 걸렸지만, D를 10분만에 풀어서 커버쳤다.. D 풀때, 직관 미쳤다.. 이번 라운드는 프리텟이 너무 약해서 시스텟에서 BC 터진 사람이 수백명 ㄷㄷ.
난 숙청의 칼날에서 무사히 살아남아 퍼플 퍼포 뽑아내고 블루 갔지롱~

A. Digit Minimization

0이 포함되지 않은 정수 N이 주어진다. 다음 과정을 반복한다. N의 숫자 두개를 고르고 위치를 바꾼다. N의 맨 오른쪽 숫자를 지운다. 이 과정을 반복하면 1개 숫자만 남게 되는데, 이 수가 가장 작은 수가 되게 하라.

풀이

손으로 몇 번 써보면 알 수 있다.

ifN<103:    return    N[1]else:    return    min(N)if \quad N < 10^3 : \; \; return \; \; N[1]\\ else : \; \; return \; \; min(N) \quad \quad

코드

for __ in range(int(input())):
    n = input()
    if len(n)==2:
        print(n[-1])
    else:
        print(min(list(n)))

B. Z mod X = C

a,b,ca, b, c 가 주어졌을 때, x,y,zx, y, z를 구하는 문제다.

x  mod  y=ay  mod  z=bz  mod  x=cx\;mod\;y=a \\ y\;mod\;z=b \\ z\;mod\;x=c \\

풀이

간단한 코드로 푸는 방법을 고민해봤다.

위 수식으로 우리가 알 수 있는 건 다음과 같다.

각각 몫을 1이라고 가정하면,

x=y+ay=z+bz=x+cx = y+a \\ y = z+b \\ z = x+c

첫번째, 두번째 수식에 따르면, x>yx > y 이고 y>zy > z 인데, 세번째 수식에 따르면 z>xz > x가 되서 성립하지 않는다.

이럴 때, 세번째 수식의 몫을 0으로 설정해주면 z=cz=c가 된다.

따라서 x=a+b+c,  y=b+c,  z=cx = a+b+c, \; y = b+c,\; z = c 이다.

코드

for __ in range(int(input())):
    a, b, c = map(int, input().split())
    print(a+b+c, b+c, c)

C. Column Swapping

NMN*M 크기의 배열이 주어진다. 배열의 두 열을 단 한 번만 swap해서, 각 행을 단조 증가 상태로 만들 수 있지 확인하는 문제다.

풀이

주어진 배열을 AA라 하자. AA의 각 행이 정렬된 배열 BB를 만든다.

AABB의 각 원소를 비교하며, swap이 발생한 column을 vv에 저장한다.

vv의 길이가 2보다 크면, 3개 이상의 column을 swap 해야 하므로 1-1을 리턴한다.

v의 길이가 0이라면, swap할 필요가 없으므로 1,11, 1을 리턴한다. 남은 건 vv의 길이가 2일 때이다.

vv의 두 원소 ans1,ans2ans1, ans2는 swap할 column의 번호다.

AAans1,ans2ans1, ans2 column을 swap 했을 때, 결과가 동일하다면 ans1,ans2ans1, ans2가 정답이다.

그렇지 않으면 swap할 방법이 없으므로 1-1을 리턴한다.

코드

import sys
input = sys.stdin.readline


def solve():
    n, m = map(int, input().split())
    A = [list(map(int, input().split())) for __ in range(n)]
    B = []
    for i in range(n):
        B.append(list(sorted(A[i])))
    
    v = []
    for j in range(m):
        for i in range(n):
            if A[i][j] != B[i][j]:
                v.append(j)
                break
    
    if len(v) > 2:
        return [-1]
    
    if len(v) == 0:
        return [1, 1]
    
    ans1, ans2 = v
    
    c1, c2 = [0]*n, [0]*n
    for i in range(n):
        c1[i] = B[i][ans1]
        c2[i] = A[i][ans2]
    
    if c1==c2:
        return [ans1+1, ans2+1]
    return [-1]


for __ in range(int(input())):
    print(*solve())

D. Traps

1부터 N까지 길에 함정이 N개 있다. ii번 길을 지나면, aia_i 피해를 입는다. 점프를 하면 해당 길을 지나칠 수 있다. 최대 KK번 점프를 할 수 있다. 점프를 할 때마다, 점프 후에 받는 피해가 11씩 커진다. 길을 지나갈 때, 받는 최소 피해를 구해라.

풀이

n,k2105n, k \leq 2*10^5 이므로 O(n)O(n) 풀이나 O(nlogn)O(n log n) 풀이를 사용해야 한다.

dp로 할까 했지만, dp의 경우 O(n2)O(n^2) 라서 안되고, 이건 무조건 O(n)O(n)으로 풀어야 하고 문제 특성상 그리디라 생각했다.

난 점프를 할 때 증가하는 가중치가 단조 증가라는 걸 보고 ai+ia_i+i를 기준으로 정렬하면 될거라 생각했다.

우선, 점프는 전부 써야 정답이 최소가 된다.

같은 점프도 최대한 늦게 쓸 수록 정답이 최소가 된다.

점프를 쓸 때마다 추가 피해는 증가하고, 이는 단조 증가 함수 형태를 띈다.

해당 위치가 정렬 기준에 있어서 유의미한 가중치가 될거라 생각해서,, 그리고 정답이었다.

여기서부터는 증명이다.

ii번째에서 점프를 하면 그 점프로 인해 받는 피해는 총 NiN-i 이다. 남은 NiN-i 동안 11의 피해를 계속 받으므로..

여기서 문제는 앞으로 지나갈 곳을 NiN-i 개라고 생각한 거다.

우리는 점프 횟수를 모두 쓸 거기 때문에 NiN-i에 남은 점프 횟수를 빼야 한다.

첫 점프에서 NiN-i 피해를 입는다고 가정하면, 우리는 K1K-1 만큼의 피해를 더 입은 거다. 실제로 받는 피해는 (Ni)(K1)(N-i)-(K-1) 이다.

총 K번의 점프에서 우리가 받는 초과 피해는 K1,K2,...,0K-1, K-2, ... , 0으로 총 K(K1)2{K*(K-1)} \over{2}이다.

여기서 생각해보면, 우리가 받는 모든 피해는 ii에만 국한된다.

각 단계에서 받는 피해는 a[i](ni)a[i]-(n-i) 이다.

a[i]+ia[i]+i를 기준으로 정렬해서 그리디하게 풀어주면 된다!

코드

import sys
input = sys.stdin.readline 
 
 
def solve():
    n, k = map(int, input().split())
    arr = list(map(int, input().split()))
    a = [(arr[i]+i, i) for i in range(n)]
    a.sort()
    
    ans = []
    for i in range(n-k):
        ans.append(a[i][1])
    ans.sort(reverse=True)
    
    w = 0
    ret = 0
    for i in range(n):
        if not ans:
            break
        if i==ans[-1]:
            ret += w+arr[i]
            ans.pop()
        else:
            w += 1
        
    return ret
 
 
for __ in range(int(input())):
    # solve()
    # print('YES' if solve() else 'NO')
    print(solve())
profile
Codeforces와 USACO 풀이를 기록합니다. 이전 글도 계속 업데이트 됩니다.

0개의 댓글