Loading [MathJax]/jax/output/CommonHTML/jax.js

카테고리 없음

2022 신촌지역 대학생 프로그래밍 대회 동아리 연합 여름 대회 (SUAPC 2022 Summer) Open Contest

닻과매 2022. 9. 5. 22:17

https://www.acmicpc.net/contest/view/849

 

2022 신촌지역 대학생 프로그래밍 대회 동아리 연합 여름 대회 (SUAPC 2022 Summer) Open Contest

 

www.acmicpc.net

 

 

 

 

 

 

 


6문제 풀었습니다. 생각보다 잘한 듯?

수학적인 사고력을 요하는 문제가 많네요.

 

 

A

, ,

double 이차원 배열 dp를 다음과 같이 정의합시다:

dp[l][k] = (최솟값이 0, 최댓값이 l인 구간에서 k를 찾는 기댓값)

경우의 수를 적당히 잘 나누어주어 기댓값을 저장합니다.

시간 복잡도는 O(24002 + N)입니다.

 

B

그냥 구현

 

C
N106이라는 건 (아마) O(N2) 풀이가 안 된다는 거고, 딱히 정렬을 하는 방식을 사용할 거 같지 않으므로 O(NlogN) 풀이도 아닐 겁니다. 그러므로, O(N) 시간 복잡도를 갖는, 적당한 방법을 직관적으로 찾기를 요구하는 문제인 듯합니다.

일단 N이 적혀있는 카드는 가장 먼저 뽑아야 합니다: 안 그러면 N을 적혀있는 카드를 뽑는 사람은 패스를 2번 이상 받게 됩니다. 이후 생각이 잘 안 나서, N12에 대해서 브루트포스로 찍어보니, N이 짝수일 때만 정답이 구해지더라고요. 그래서 일단 짝수일때만 가능하다고 생각하고 풀었습니다. 풀고나서 생각해보니, N3 이상의 홀수일 때

N1n=1n=N(N1)20(modN) 이기에, 처음 시작하는 사람은 무조건 2번 이상 패스를 받습니다.

N이 짝수일 때 처음 시작점을 1이라고 한다면, 2N13N2... 에게 패스를 하면 된다는 사실을 관찰할 수 있습니다. '직관적인 관찰'이라 어떻게 생각했는지 모르겠네요.

그리고 N이 홀수라도 N=1일 때는 됩니다. 이 경우만 예외처리해주면 됩니다.

 

F

일반성을 잃지 않고, A1,...ANA1<A2<...<AN로 정합시다.

차의 개수의 최댓값

Ai=2i1로 설정하면 차이의 개수는 N(N1)/2개로 최대입니다. 229<10억이라 가능합니다.

차의 개수의 최솟값

|A2A1|<|A3A1|<...<|ANA1| 이므로, 차의 개수의 최솟값은 최소 N1개입니다.

그리고 간단히 Ai=i로 결정하면 차의 개수가 N1개가 됩니다.

 

I

좀 디버깅이 끔찍한 case-work 문제입니다. 일단, 케이스를 좀 편하게 나누기 위해 row, col별로 씨앗의 개수를 세주고, 씨앗이 있는 row, col의 수, 그리고 씨앗이 뿌려져있는 칸의 수를 세줍니다.

1) 만약 씨앗이 뿌려져있는 칸의 수가 2K개라면 겹쳐서 씨앗을 뿌리지 않았으므로 1 출력

2) 1)이 아니라면: 2K - '씨앗이 뿌려져있는 칸의 수'개만큼 씨앗을 겹쳐뿌렸습니다. case를 나누어,

 I) 씨앗이 있는 row의 수가 1인 경우: 두 명 모두 한 줄에 겹쳐 뿌렸다는 뜻입니다. 몇 개가 겹쳤는지 '씨앗이 뿌려져있는 칸의 수'를 통해 구하고, '겹칠 수밖에 없는' 위치의 씨앗의 좌표를 저장해 출력합니다.

 II) 씨앗이 있는 col의 수가 1인 경우: I)이랑 row/col 바꿔서 풀면 됩니다.

 III) 그외: 한 명은 세로로, 한 명은 가로로 씨앗을 뿌렸습니다. 이 경우 최대 1곳에서만 만나며, 위 정보를 통해 빠르게 구해줍니다.

K=1일 때의 예외 처리를 해줘야할 거 같지만, 2) - I)에서 잘 처리가 됩니다.

그와 별개로 실수하기 참 쉬운 문제입니다. 저는 한 곳에서만 N,M을 바꿔썼다가 디버깅이 엄청 오래 걸렸습니다.

 

M

주제별로 뽑을 수 있는 경우의 수를 Xi라고 하면, 정답 X=Ni=1Xi 이고,

Xi=Nn=1(Ain)(Bin) where N=min(Ai,Bi) 입니다.

그리고

Xi=Nn=1(Ain)(Bin)=(Ai+BiN)1

이 됩니다. 이는 

(1+x)Ai+Bi=(1+x)Ai(1+x)BiN차항의 계수를 비교하면 알 수 있습니다. 찾아보니 Vandermonde's Identity라고 합니다. 수학 전공한거 맞나? ㅋㅋ... 잘 모르겠어서 구글에 대충 쳐서 구했습니다.

그리고, 오일러 소정리를 이용하면, 임의의 소수 p에 대해,

(Ai+BiAi)(Ai+Bi)!Ai!Bi!(Ai+Bi)!(Ai)!p2(Bi)!p2(modp)

가 성립합니다. 본 문제에서 p=109+7입니다.

1! 부터 (A+B)!을 미리 구하고, 분할정복을 이용하여 p제곱을 계산하기에, 각 쿼리를 O(logp)에 처리할 수 있습니다. 시작 복잡도는 O((A+B)+Nlogp).

 

글 정리하겠다고 학부 시절에는 쳐다도 안 봤던 LaTex 문법을 다 써보네요ㅋㅋ

생각보다 쓰는 방법이 간단해서, 시간 복잡도 'O(N)' 정도의 표현에 대해서는 계속 써야겠습니다.