├── .gitignore ├── codes ├── python │ ├── chap01 │ │ ├── answer_A01.py │ │ ├── answer_A04.py │ │ ├── answer_A05.py │ │ ├── answer_A02.py │ │ └── answer_A03.py │ ├── chap06 │ │ ├── answer_A36.py │ │ ├── answer_A40.py │ │ ├── answer_A37.py │ │ ├── answer_A41.py │ │ ├── answer_A43.py │ │ ├── answer_A39.py │ │ ├── answer_A45.py │ │ ├── answer_A38.py │ │ ├── answer_A42.py │ │ └── answer_A44.py │ ├── chap05 │ │ ├── answer_A31.py │ │ ├── answer_A27.py │ │ ├── answer_A33.py │ │ ├── answer_A29.py │ │ ├── answer_A26.py │ │ ├── answer_A32.py │ │ ├── answer_A28.py │ │ ├── answer_A35.py │ │ ├── answer_A30.py │ │ └── answer_A34.py │ ├── chap10 │ │ ├── answer_A71.py │ │ ├── answer_A74.py │ │ ├── answer_A77.py │ │ ├── answer_A75.py │ │ └── answer_A76.py │ ├── chap08 │ │ ├── answer_A54.py │ │ ├── answer_A51.py │ │ ├── answer_A52.py │ │ ├── answer_A53.py │ │ ├── answer_A60.py │ │ └── answer_A57.py │ ├── chap04 │ │ ├── answer_A16.py │ │ ├── answer_A22.py │ │ ├── answer_A19.py │ │ ├── answer_A24_withoutDP.py │ │ ├── answer_A25.py │ │ ├── answer_A20.py │ │ ├── answer_A24.py │ │ ├── answer_A18.py │ │ ├── answer_A17.py │ │ ├── answer_A23.py │ │ └── answer_A21.py │ ├── chap02 │ │ ├── answer_A06.py │ │ ├── answer_A07.py │ │ ├── answer_A10.py │ │ ├── answer_A08.py │ │ └── answer_A09.py │ ├── chap03 │ │ ├── answer_A15.py │ │ ├── answer_A13.py │ │ ├── answer_A11.py │ │ ├── answer_A12.py │ │ └── answer_A14.py │ └── chap09 │ │ ├── answer_A65.py │ │ ├── answer_A61.py │ │ └── answer_A63.py ├── cpp │ ├── chap07 │ │ ├── code_7-12.cpp │ │ ├── code_7-13.cpp │ │ ├── code_7-01.cpp │ │ ├── code_7-02.cpp │ │ ├── code_7-05.cpp │ │ ├── code_7-04.cpp │ │ ├── code_7-07.cpp │ │ ├── code_7-11.cpp │ │ ├── code_7-14.cpp │ │ ├── code_7-08.cpp │ │ ├── code_7-09.cpp │ │ ├── code_7-06.cpp │ │ └── code_7-10.cpp │ ├── chap09 │ │ ├── code_9-03.cpp │ │ ├── code_9-05.cpp │ │ ├── code_9-02.cpp │ │ ├── code_9-04.cpp │ │ ├── answer_A65.cpp │ │ ├── answer_A61.cpp │ │ ├── answer_A69.cpp │ │ ├── code_9-01.cpp │ │ ├── answer_A65_DFS.cpp │ │ ├── answer_A67.cpp │ │ ├── answer_A63.cpp │ │ └── answer_A62.cpp │ ├── chap01 │ │ ├── answer_A01.cpp │ │ ├── code_1-01.cpp │ │ ├── code_1-03.cpp │ │ ├── answer_A04.cpp │ │ ├── answer_A05.cpp │ │ ├── code_1-02.cpp │ │ ├── answer_A02.cpp │ │ ├── answer_A03.cpp │ │ └── code_1-04.cpp │ ├── chap03 │ │ ├── code_3-02.cpp │ │ ├── code_3-01.cpp │ │ ├── answer_A11.cpp │ │ ├── answer_A13.cpp │ │ ├── answer_A12.cpp │ │ └── answer_A15.cpp │ ├── chap05 │ │ ├── code_5-01.cpp │ │ ├── code_5-03.cpp │ │ ├── answer_A31.cpp │ │ ├── code_5-05.cpp │ │ ├── answer_A27.cpp │ │ ├── answer_A33.cpp │ │ ├── code_5-04.cpp │ │ ├── answer_A26.cpp │ │ ├── answer_A32.cpp │ │ ├── answer_A29.cpp │ │ ├── answer_A28.cpp │ │ ├── answer_A35.cpp │ │ ├── answer_A30.cpp │ │ ├── code_5-02.cpp │ │ └── answer_A34.cpp │ ├── chap04 │ │ ├── code_4-01.cpp │ │ ├── answer_A16.cpp │ │ ├── answer_A24.cpp │ │ ├── answer_A22.cpp │ │ ├── answer_A24_withoutDP.cpp │ │ ├── answer_A25.cpp │ │ ├── answer_A19.cpp │ │ ├── answer_A18.cpp │ │ └── answer_A20.cpp │ ├── chap08 │ │ ├── code_8-03.cpp │ │ ├── code_8-05.cpp │ │ ├── code_8-04.cpp │ │ ├── code_8-06.cpp │ │ ├── code_8-01.cpp │ │ ├── code_8-02.cpp │ │ ├── answer_A51.cpp │ │ ├── answer_A52.cpp │ │ ├── answer_A55.cpp │ │ ├── answer_A53.cpp │ │ ├── answer_A54.cpp │ │ ├── answer_A57.cpp │ │ └── answer_A60.cpp │ ├── chap06 │ │ ├── answer_A36.cpp │ │ ├── answer_A43.cpp │ │ ├── code_6-02.cpp │ │ ├── answer_A37.cpp │ │ ├── answer_A40.cpp │ │ ├── answer_A41.cpp │ │ ├── answer_A38.cpp │ │ ├── answer_A45.cpp │ │ ├── code_6-01.cpp │ │ ├── answer_A44.cpp │ │ ├── answer_A42.cpp │ │ └── answer_A39.cpp │ ├── chap02 │ │ ├── code_2-01.cpp │ │ ├── answer_A06.cpp │ │ ├── answer_A07.cpp │ │ ├── answer_A10.cpp │ │ └── answer_A08.cpp │ └── chap10 │ │ ├── code_10-01.cpp │ │ ├── code_10-02.cpp │ │ ├── answer_A71.cpp │ │ ├── answer_A74.cpp │ │ ├── answer_A77.cpp │ │ └── answer_A76.cpp └── java │ ├── chap01 │ ├── answer_A01.java │ ├── answer_A04.java │ ├── answer_A05.java │ ├── answer_A02.java │ └── answer_A03.java │ ├── chap06 │ ├── answer_A36.java │ ├── answer_A41.java │ ├── answer_A43.java │ ├── answer_A37.java │ ├── answer_A40.java │ ├── answer_A45.java │ ├── answer_A39.java │ ├── answer_A38.java │ ├── answer_A44.java │ └── answer_A42.java │ ├── chap05 │ ├── answer_A31.java │ ├── answer_A33.java │ ├── answer_A27.java │ ├── answer_A32.java │ ├── answer_A26.java │ ├── answer_A29.java │ ├── answer_A35.java │ └── answer_A28.java │ ├── chap04 │ ├── answer_A16.java │ ├── answer_A22.java │ ├── answer_A25.java │ ├── answer_A24.java │ ├── answer_A20.java │ ├── answer_A19.java │ └── answer_A18.java │ ├── chap10 │ └── answer_A71.java │ ├── chap02 │ ├── answer_A06.java │ ├── answer_A07.java │ └── answer_A10.java │ ├── chap08 │ ├── answer_A51.java │ ├── answer_A52.java │ ├── answer_A53.java │ ├── answer_A55.java │ └── answer_A54.java │ └── chap03 │ ├── answer_A11.java │ ├── answer_A13.java │ └── answer_A15.java └── editorial ├── chap01 ├── python │ ├── answer_B01.py │ ├── answer_B04.py │ ├── answer_B02.py │ └── answer_B03.py └── cpp │ ├── answer_B01.cpp │ ├── answer_B02.cpp │ ├── answer_B04.cpp │ └── answer_B03.cpp ├── chap06 ├── python │ ├── answer_B45.py │ ├── answer_B36.py │ ├── answer_B43.py │ ├── answer_B41.py │ ├── answer_B40.py │ ├── answer_B44.py │ ├── answer_B39.py │ ├── answer_B38.py │ ├── answer_B37.py │ └── answer_B42.py └── cpp │ ├── answer_B45.cpp │ ├── answer_B36.cpp │ ├── answer_B43.cpp │ ├── answer_B41.cpp │ ├── answer_B40.cpp │ ├── answer_B44.cpp │ ├── answer_B39.cpp │ ├── answer_B38.cpp │ └── answer_B42.cpp ├── final └── cpp │ ├── answer_C01.cpp │ ├── answer_C06.cpp │ ├── answer_C05.cpp │ ├── answer_C02.cpp │ ├── answer_C09.cpp │ ├── answer_C04.cpp │ ├── answer_C10.cpp │ ├── answer_C07.cpp │ ├── answer_C03.cpp │ ├── answer_C12.cpp │ ├── answer_C11.cpp │ └── answer_C18.cpp ├── chap05 ├── answer_B28.py ├── python │ ├── answer_B28.py │ ├── answer_B27.py │ ├── answer_B34.py │ ├── answer_B29.py │ ├── answer_B26.py │ ├── answer_B33.py │ ├── answer_B31.py │ ├── answer_B32.py │ └── answer_B30.py ├── answer_B27.py ├── answer_B34.py ├── answer_B29.py ├── answer_B26.py ├── answer_B28.cpp ├── cpp │ ├── answer_B28.cpp │ ├── answer_B27.cpp │ ├── answer_B33.cpp │ ├── answer_B26.cpp │ ├── answer_B34.cpp │ ├── answer_B29.cpp │ ├── answer_B31.cpp │ └── answer_B32.cpp ├── answer_B33.py ├── answer_B27.cpp ├── answer_B32.py ├── answer_B31.py ├── answer_B33.cpp ├── answer_B26.cpp ├── answer_B34.cpp ├── answer_B29.cpp ├── answer_B31.cpp ├── answer_B32.cpp └── answer_B30.py ├── chap08 ├── python │ ├── answer_B51.py │ ├── answer_B54.py │ ├── answer_B57.py │ ├── answer_B52.py │ ├── answer_B53.py │ ├── answer_B59.py │ └── answer_B58.py └── cpp │ ├── answer_B54.cpp │ ├── answer_B51.cpp │ ├── answer_B52.cpp │ ├── answer_B53.cpp │ └── answer_B57.cpp ├── chap09 ├── python │ ├── answer_B61.py │ ├── answer_B65.py │ ├── answer_B62.py │ ├── answer_B63.py │ ├── answer_B67.py │ └── answer_B64.py └── cpp │ └── answer_B61.cpp ├── chap04 ├── python │ ├── answer_B16.py │ ├── answer_B22.py │ ├── answer_B21.py │ ├── answer_B20.py │ ├── answer_B19.py │ ├── answer_B23.py │ ├── answer_B24.py │ └── answer_B17.py └── cpp │ ├── answer_B16.cpp │ ├── answer_B22.cpp │ ├── answer_B19.cpp │ ├── answer_B21.cpp │ └── answer_B20.cpp ├── chap03 ├── python │ ├── answer_B12.py │ ├── answer_B11.py │ ├── answer_B13.py │ └── answer_B14.py └── cpp │ ├── answer_B11.cpp │ ├── answer_B12.cpp │ └── answer_B13.cpp └── chap02 ├── python ├── answer_B07.py ├── answer_B09.py ├── answer_B06.py └── answer_B08.py └── cpp ├── answer_B07.cpp └── answer_B06.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /codes/python/chap01/answer_A01.py: -------------------------------------------------------------------------------- 1 | N = int(input()) # 입력 2 | print(N * N) # 출력 3 | -------------------------------------------------------------------------------- /editorial/chap01/python/answer_B01.py: -------------------------------------------------------------------------------- 1 | A, B = map(int, input().split()) # 입력 2 | print(A + B) # 출력 3 | -------------------------------------------------------------------------------- /codes/cpp/chap07/code_7-12.cpp: -------------------------------------------------------------------------------- 1 | int func(int N) { 2 | if (N == 1) return 1; 3 | return func(N - 1) + N; 4 | } 5 | -------------------------------------------------------------------------------- /codes/cpp/chap07/code_7-13.cpp: -------------------------------------------------------------------------------- 1 | int GCD(int A, int B) { 2 | if (B == 0) return A; 3 | return GCD(B, A % B); 4 | } 5 | -------------------------------------------------------------------------------- /codes/cpp/chap07/code_7-01.cpp: -------------------------------------------------------------------------------- 1 | // a 이상 b 이하의 정수를 무작위로 반환하는 함수 2 | int RandInt(int a, int b) { 3 | return a + rand() % (b - a + 1); 4 | } 5 | -------------------------------------------------------------------------------- /codes/cpp/chap09/code_9-03.cpp: -------------------------------------------------------------------------------- 1 | G[pos][i].cap -= flow; // 에지의 용량을 flow 감소시킨다 2 | G[G[pos][i].to][G[pos][i].rev].cap += flow; // 역에지의 용량을 flow 증가시킨다 3 | -------------------------------------------------------------------------------- /editorial/chap06/python/answer_B45.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | a, b, c = map(int, input().split()) 3 | 4 | # 출력 5 | if a + b + c == 0: 6 | print("Yes") 7 | else: 8 | print("No") 9 | -------------------------------------------------------------------------------- /codes/python/chap06/answer_A36.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, K = map(int, input().split()) 3 | 4 | # 출력 5 | if K >= 2*N-2 and K%2 == 0: 6 | print("Yes") 7 | else: 8 | print("No") 9 | -------------------------------------------------------------------------------- /codes/cpp/chap07/code_7-02.cpp: -------------------------------------------------------------------------------- 1 | struct State { 2 | int score; // 잠정 점수 3 | int X[29]; // 현재 배열 X의 값 4 | char LastMove; // 마지막 동작('A' 또는 'B') 5 | int LastPos; //Beam[i-1][ 어디 ]에서 전이했는가 6 | }; 7 | -------------------------------------------------------------------------------- /codes/cpp/chap07/code_7-05.cpp: -------------------------------------------------------------------------------- 1 | int CurrentPlace = 0; 2 | for (int i = T; i >= 1; i--) { 3 | Answer[i] = Beam[i][CurrentPlace].LastMove; 4 | CurrentPlace = Beam[i][CurrentPlace].LastPos; 5 | } 6 | -------------------------------------------------------------------------------- /codes/cpp/chap01/answer_A01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | int N; 6 | cin >> N; // 입력 7 | cout << N * N << endl; // 출력 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /codes/cpp/chap01/code_1-01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | int N; 6 | cin >> N; // 입력 7 | cout << N + N << endl; // 출력 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /codes/cpp/chap07/code_7-04.cpp: -------------------------------------------------------------------------------- 1 | // sort 함수의 순서를 결정한다(점수가 높은 쪽이 '크다'고 한다) 2 | bool operator>(const State& a1, const State& a2) { 3 | if (a1.score > a2.score) return true; 4 | else return false; 5 | } 6 | -------------------------------------------------------------------------------- /codes/cpp/chap03/code_3-02.cpp: -------------------------------------------------------------------------------- 1 | // 정수 x가 몇 번째에 위치하는지 반환한다 2 | int search(int x) { 3 | int pos = lower_bound(A + 1, A + N + 1, x) - A; 4 | if (pos <= N && A[pos] == x) return pos; 5 | return -1; 6 | } 7 | -------------------------------------------------------------------------------- /codes/cpp/chap05/code_5-01.cpp: -------------------------------------------------------------------------------- 1 | // x가 소수일 때 true, 소수가 아닐 때 false를 반환한다 2 | bool isPrime(int x) { 3 | for (int i = 2; i <= x - 1; i++) { 4 | if (x % i == 0) return false; 5 | } 6 | return true; 7 | } 8 | -------------------------------------------------------------------------------- /codes/cpp/chap09/code_9-05.cpp: -------------------------------------------------------------------------------- 1 | for (int k = 1; k <= N; k++) { 2 | for (int i = 1; i <= N; i++) { 3 | for (int j = 1; j <= N; j++) { 4 | d[i][j] = min(d[i][j], d[i][k] + d[k][j]); 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /codes/python/chap05/answer_A31.py: -------------------------------------------------------------------------------- 1 | N = int(input()) 2 | A1 = (N // 3) # 3으로 나누어떨어지는 수의 개수 3 | A2 = (N // 5) # 5로 나누어떨어지는 수의 개수 4 | A3 = (N // 15) # 3, 5 모두로 나누어떨어지는 수(= 15의 배수)의 개수 5 | print(A1 + A2 - A3) 6 | -------------------------------------------------------------------------------- /codes/cpp/chap04/code_4-01.cpp: -------------------------------------------------------------------------------- 1 | // 답은 dp[1], dp[2], ..., dp[N]의 최댓값 2 | for (int i = 1; i <= N; i++) { 3 | dp[i] = 1; 4 | for (int j = 1; j <= i - 1; j++) { 5 | if (A[j] < A[i]) dp[i] = max(dp[i], dp[j] + 1); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /editorial/final/cpp/answer_C01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | // 입력 6 | int N; 7 | cin >> N; 8 | 9 | // 출력 10 | cout << N * 11 / 10 << endl; 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /codes/cpp/chap07/code_7-07.cpp: -------------------------------------------------------------------------------- 1 | // 현재 점수를 반환하는 함수 2 | int GetScore() { 3 | int sum = 0; 4 | for (int i = 0; i < N; i++) { 5 | for (int j = 0; j < N; j++) sum += abs(A[i][j] - B[i][j]); 6 | } 7 | return 200000000 - sum; 8 | } 9 | -------------------------------------------------------------------------------- /editorial/chap01/cpp/answer_B01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | // 입력 6 | int A, B; 7 | cin >> A >> B; 8 | 9 | // 출력 10 | cout << A + B << endl; 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /codes/cpp/chap08/code_8-03.cpp: -------------------------------------------------------------------------------- 1 | auto itr = S.lower_bound(x); 2 | if (itr == S.end()) { // x가 S의 최댓값보다 클 때 itr==S.end()를 만족한다 3 | cout << "-1" << endl; // 이런 경우는 -1을 출력 4 | } 5 | else { 6 | cout << (*itr) << endl; // 그렇지 않은 경우는 일반적으로 처리 7 | } 8 | -------------------------------------------------------------------------------- /codes/cpp/chap08/code_8-05.cpp: -------------------------------------------------------------------------------- 1 | void update(int pos, int x) { // 셀 i에 쓰여진 정수를 dat[i]로 나타낸다 2 | pos = pos + siz - 1; 3 | dat[pos] = x; 4 | while (pos >= 2) { 5 | pos /= 2; 6 | dat[pos] = max(dat[pos * 2], dat[pos * 2 + 1]); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /codes/python/chap01/answer_A04.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | 4 | # 윗자리부터 순서대로 '2진법으로 변환한 값'을 구한다 5 | for x in [9,8,7,6,5,4,3,2,1,0]: 6 | wari = (2 ** x) 7 | print((N // wari) % 2, end='') 8 | 9 | # 마지막에 줄바꿈한다 10 | print("") 11 | -------------------------------------------------------------------------------- /editorial/chap05/answer_B28.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | 4 | # 피보나치 수 계산 5 | a = [ None ] * (N + 1) 6 | a[1] = 1 7 | a[2] = 1 8 | for i in range(3, N+1): 9 | a[i] = (a[i-1] + a[i-2]) % 1000000007 10 | 11 | # 출력 12 | print(a[N]) 13 | -------------------------------------------------------------------------------- /editorial/chap05/python/answer_B28.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | 4 | # 피보나치 수 계산 5 | a = [ None ] * (N + 1) 6 | a[1] = 1 7 | a[2] = 1 8 | for i in range(3, N+1): 9 | a[i] = (a[i-1] + a[i-2]) % 1000000007 10 | 11 | # 출력 12 | print(a[N]) 13 | -------------------------------------------------------------------------------- /codes/cpp/chap06/answer_A36.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | int N, K; 6 | cin >> N >> K; 7 | if (K >= 2 * N - 2 && K % 2 == 0) cout << "Yes" << endl; 8 | else cout << "No" << endl; 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /codes/java/chap01/answer_A01.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | int N = sc.nextInt(); // 입력 부분 7 | System.out.println(N * N); // 출력 부분 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /codes/cpp/chap09/code_9-02.cpp: -------------------------------------------------------------------------------- 1 | // 노드 x의 루트를 반환하는 함수 2 | // 주: 부모를 갖지 않는 노드의 경우에는 'par[x] = -1'로 기록한다 3 | int root(int x) { 4 | while (true) { 5 | if (par[x] == -1) break; // 1개 앞(부모)이 없으면 여기가 루트 6 | x = par[x]; // 1 개 앞(부모)으로 진행한다 7 | } 8 | return x; 9 | } 10 | -------------------------------------------------------------------------------- /codes/python/chap01/answer_A05.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, K = map(int, input().split()) 3 | Answer = 0 4 | 5 | # 완전 탐색 6 | for x in range(1, N+1): 7 | for y in range(1, N+1): 8 | z = K - x - y 9 | if z >= 1 and z <= N: 10 | Answer += 1 11 | 12 | # 출력 13 | print(Answer) 14 | -------------------------------------------------------------------------------- /editorial/chap08/python/answer_B51.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | S = input() 3 | 4 | # 왼쪽부터 순서대로 살펴본다 5 | # 문자열은 0번째 문자부터 시작한다는 점에 유의하세요. 6 | Stack = [] 7 | for i in range(len(S)): 8 | if S[i] == '(': 9 | Stack.append(i + 1) 10 | if S[i] == ')': 11 | print(Stack.pop(), i + 1) 12 | -------------------------------------------------------------------------------- /codes/cpp/chap05/code_5-03.cpp: -------------------------------------------------------------------------------- 1 | // 정수 A와 B의 최대 공약수를 반환하는 함수 2 | // GCD는 최대 공약수(Greatest Common Divisor)의 약자 3 | int GCD(int A, int B) { 4 | int ret = 0; 5 | for (int x = 1; x <= min(A, B); x++) { 6 | if (A % x == 0 && B % x == 0) ret = x; 7 | } 8 | return ret; 9 | } 10 | -------------------------------------------------------------------------------- /editorial/chap01/python/answer_B04.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = input() 3 | 4 | # 답을 구한다 5 | Answer = 0 6 | for i in range(len(N)): 7 | keta = 0 8 | kurai = (2 ** (len(N) - 1 - i)) 9 | if N[i] == '1': 10 | keta = 1 11 | Answer += keta * kurai 12 | 13 | # 출력 14 | print(Answer) 15 | -------------------------------------------------------------------------------- /codes/cpp/chap08/code_8-04.cpp: -------------------------------------------------------------------------------- 1 | // S = {15, 35, 50}의 상태에서 시작하는 것을 생각한다 2 | auto itr1 = S.lower_bound(40); 3 | cout << (*itr1) << endl; // 50이 출력된다 4 | 5 | itr1--; 6 | cout << (*itr1) << endl; // (1개 작다) 35가 출력된다 7 | 8 | itr1++; 9 | cout << (*itr1) << endl; // (1개 크다) 50이 출력된다 10 | -------------------------------------------------------------------------------- /editorial/chap01/python/answer_B02.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | A, B = map(int, input().split()) 3 | 4 | # 답을 구한다 5 | Answer = False 6 | for i in range(A, B + 1): 7 | if 100 % i == 0: 8 | Answer = True 9 | 10 | # 출력 11 | if Answer == True: 12 | print("Yes") 13 | else: 14 | print("No") 15 | -------------------------------------------------------------------------------- /codes/cpp/chap07/code_7-11.cpp: -------------------------------------------------------------------------------- 1 | // 함수 Randouble은 7.3절의 해답 예를 참조 2 | double TEMP = 180.0 - 179.0 * (clock() - ti) / TIMELIMIT; 3 | double PROB = exp(min(0.0, 1.0 * (NewScore - CurrentScore) / TEMP)); 4 | if (Randouble() < PROB) CurrentScore = NewScore; 5 | else Change(t, old_x, old_y, old_h); 6 | -------------------------------------------------------------------------------- /codes/cpp/chap02/code_2-01.cpp: -------------------------------------------------------------------------------- 1 | for (int d = 1; d <= D; d++) { 2 | int Answer = 0; 3 | 4 | // for 문으로 최댓값을 계산한다(변수 i는 방 번호를 나타낸다) 5 | for (int i = 1; i <= N; i++) { 6 | if (L[d] <= i && i <= R[d]) continue; 7 | Answer = max(Answer, A[i]); 8 | } 9 | cout << Answer << endl; 10 | } 11 | -------------------------------------------------------------------------------- /codes/python/chap05/answer_A27.py: -------------------------------------------------------------------------------- 1 | def GCD(A, B): 2 | while A >= 1 and B >= 1: 3 | if A >= B: 4 | A = A % B # A의 값을 변경하는 경우 5 | else: 6 | B = B % A # B의 값을 변경하는 경우 7 | if A >= 1: 8 | return A 9 | return B 10 | 11 | # 입력 12 | A, B = map(int, input().split()) 13 | print(GCD(A, B)) 14 | -------------------------------------------------------------------------------- /editorial/chap06/cpp/answer_B45.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | long long a, b, c; 5 | 6 | int main() { 7 | // 입력 8 | cin >> a >> b >> c; 9 | 10 | // 출력 11 | if (a + b + c == 0) cout << "Yes" << endl; 12 | else cout << "No" << endl; 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /editorial/chap06/python/answer_B36.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, K = map(int, input().split()) 3 | S = input() 4 | 5 | # ON으로 되어 있는 것의 개수를 센다 6 | numON = 0 7 | for i in range(N): 8 | if S[i] == '1': 9 | numON += 1 10 | 11 | # 답을 출력 12 | if numON%2 == K%2: 13 | print("Yes") 14 | else: 15 | print("No") 16 | -------------------------------------------------------------------------------- /editorial/final/cpp/answer_C06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | // 입력 6 | int N; 7 | cin >> N; 8 | 9 | // 출력 10 | cout << N << endl; 11 | for (int i = 1; i <= N; i++) { 12 | cout << i << " " << i % N + 1 << endl; 13 | } 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /codes/python/chap05/answer_A33.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | A = list(map(int, input().split())) 4 | 5 | # 전부 XOR한 값(Nim sum)을 구한다 6 | XOR_Sum = A[0] 7 | for i in range(1,N): 8 | XOR_Sum = (XOR_Sum ^ A[i]) 9 | 10 | # 출력 11 | if XOR_Sum >= 1: 12 | print("First") 13 | else: 14 | print("Second") 15 | -------------------------------------------------------------------------------- /editorial/chap05/answer_B27.py: -------------------------------------------------------------------------------- 1 | def GCD(A, B): 2 | while A >= 1 and B >= 1: 3 | if A >= B: 4 | A = A % B # A의 값을 변경하는 경우 5 | else: 6 | B = B % A # B의 값을 변경하는 경우 7 | if A >= 1: 8 | return A 9 | return B 10 | 11 | # 입력 12 | A, B = map(int, input().split()) 13 | print(A * B // GCD(A, B)) 14 | -------------------------------------------------------------------------------- /codes/python/chap10/answer_A71.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | A = list(map(int, input().split())) 4 | B = list(map(int, input().split())) 5 | 6 | # 배열 정렬(A는 오름차순, B는 내림차순으로 정렬) 7 | A.sort() 8 | B.sort(reverse = True) 9 | 10 | # 답은 A[i] * B[i]의 합계 11 | print(sum([ A[i] * B[i] for i in range(N) ])) -------------------------------------------------------------------------------- /editorial/chap05/python/answer_B27.py: -------------------------------------------------------------------------------- 1 | def GCD(A, B): 2 | while A >= 1 and B >= 1: 3 | if A >= B: 4 | A = A % B # A의 값을 변경하는 경우 5 | else: 6 | B = B % A # B의 값을 변경하는 경우 7 | if A >= 1: 8 | return A 9 | return B 10 | 11 | # 입력 12 | A, B = map(int, input().split()) 13 | print(A * B // GCD(A, B)) 14 | -------------------------------------------------------------------------------- /editorial/chap06/python/answer_B43.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, M = map(int, input().split()) 3 | A = list(map(int, input().split())) 4 | 5 | # 배열 준비 6 | Incorrect = [ 0 ] * (N + 1) 7 | 8 | # 오답 수 구하기 9 | for i in range(M): 10 | Incorrect[A[i]] += 1 11 | 12 | # 답을 출력 13 | for i in range(1, N+1): 14 | print(M - Incorrect[i]) 15 | -------------------------------------------------------------------------------- /editorial/chap08/python/answer_B54.py: -------------------------------------------------------------------------------- 1 | Map = {} 2 | 3 | # 입력 4 | N = int(input()) 5 | A = [int(input()) for _ in range(N)] 6 | 7 | # 답을 구한다 8 | Answer = 0 9 | for a in A: 10 | # dict.get에는 키가 존재하지 않는 경우의 기본값을 설정할 수 있다 11 | Answer += Map.get(a, 0) 12 | Map[a] = Map.get(a, 0) + 1 13 | 14 | # 출력 15 | print(Answer) 16 | -------------------------------------------------------------------------------- /codes/python/chap06/answer_A40.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | A = list(map(int, input().split())) 4 | 5 | # 개수를 센다 6 | cnt = [ 0 ] * 101 7 | Answer = 0 8 | for i in range(N): 9 | cnt[A[i]] += 1 10 | 11 | # 답을 구한다 12 | for i in range(1, 101): 13 | Answer += cnt[i] * (cnt[i]-1) * (cnt[i]-2) // 6; 14 | print(Answer) 15 | -------------------------------------------------------------------------------- /codes/python/chap01/answer_A02.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, X = map(int, input().split()) 3 | A = list(map(int, input().split())) 4 | Answer = False 5 | 6 | # 완전 탐색(변수 Answer는 '기존에 x를 발견했는가'를 나타냄) 7 | for i in range(N): 8 | if A[i] == X: 9 | Answer = True 10 | 11 | # 출력 12 | if Answer == True: 13 | print("Yes") 14 | else: 15 | print("No") 16 | -------------------------------------------------------------------------------- /codes/cpp/chap01/code_1-03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | // 입력 부분 6 | int a, b; 7 | cin >> a >> b; 8 | 9 | // 출력 부분 10 | cout << (a & b) << endl; // a AND b 의 값을 출력 11 | cout << (a | b) << endl; // a OR b 의 값을 출력 12 | cout << (a ^ b) << endl; // a XOR b 의 값을 출력 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /editorial/chap09/python/answer_B61.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, M = map(int, input().split()) 3 | 4 | # 친구 수 세기 5 | friend = [0] * N 6 | for _ in range(M): 7 | A, B = map(int, input().split()) 8 | A -= 1 9 | B -= 1 10 | friend[A] += 1 11 | friend[B] += 1 12 | 13 | mx = max(friend) 14 | ans = friend.index(mx) 15 | print(ans + 1) 16 | -------------------------------------------------------------------------------- /codes/python/chap08/answer_A54.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | Q = int(input()) # 쿼리 개수 3 | queries = [ input().split() for i in range(Q) ] # 쿼리 정보(각 요소는 ["1", 이름을 나타내는 문자열, 점수를 나타내는 문자열] or ["2", 이름을 나타내는 문자열]로 구성됨) 4 | 5 | # 쿼리 처리 6 | Map = {} 7 | for q in queries: 8 | if q[0] == "1": 9 | Map[q[1]] = q[2] 10 | if q[0] == "2": 11 | print(Map[q[1]]) -------------------------------------------------------------------------------- /codes/python/chap06/answer_A37.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, M, B = map(int, input().split()) 3 | A = list(map(int, input().split())) 4 | C = list(map(int, input().split())) 5 | 6 | # 답 계산 7 | Answer = 0 8 | for i in range(N): 9 | Answer += A[i] * M 10 | Answer += B * N * M 11 | for j in range(M): 12 | Answer += C[j] * N 13 | 14 | # 출력 15 | print(Answer) 16 | -------------------------------------------------------------------------------- /editorial/chap04/python/answer_B16.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | H = list(map(int, input().split())) 4 | 5 | # 배열 준비 6 | dp = [ None ] * N 7 | 8 | # 동적 계획 알고리즘 9 | dp[0] = 0 10 | dp[1] = abs(H[0] - H[1]) 11 | for i in range(2, N): 12 | dp[i] = min(dp[i-1] + abs(H[i-1]-H[i]), dp[i-2] + abs(H[i-2]-H[i])) 13 | 14 | # 출력 15 | print(dp[N-1]) 16 | -------------------------------------------------------------------------------- /codes/cpp/chap05/answer_A31.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | long long N; 6 | cin >> N; 7 | long long A1 = (N / 3); // 3으로 나누어떨어지는 수의 개수 8 | long long A2 = (N / 5); // 5로 나누어떨어지는 수의 개수 9 | long long A3 = (N / 15); // 3, 5 모두로 나누어떨어지는 수(= 15의 배수)의 개수 10 | cout << A1 + A2 - A3 << endl; 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /codes/python/chap04/answer_A16.py: -------------------------------------------------------------------------------- 1 | # 입력(A, B 가 0 번부터 시작한다는 점에 유의) 2 | N = int(input()) 3 | A = list(map(int, input().split())) 4 | B = list(map(int, input().split())) 5 | 6 | # 동적 계획 알고리즘 7 | dp = [ None ] * (N+1) 8 | dp[1] = 0 9 | dp[2] = A[0] 10 | for i in range(3, N+1): 11 | dp[i] = min(dp[i-1]+A[i-2], dp[i-2]+B[i-3]) 12 | 13 | # 출력 14 | print(dp[N]) 15 | -------------------------------------------------------------------------------- /editorial/chap05/answer_B34.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, X, Y = map(int, input().split()) 3 | A = list(map(int, input().split())) 4 | 5 | # Grundy 수 계산 6 | XOR_Sum = 0 7 | for i in range(N): 8 | Grundy = [0, 0, 1, 1, 2] # 5로 나눈 나머지 Grundy 수에 대응하는 Grundy 수 9 | XOR_Sum ^= Grundy[A[i] % 5] 10 | 11 | # 출력 12 | if XOR_Sum != 0: 13 | print("First") 14 | else: 15 | print("Second") 16 | -------------------------------------------------------------------------------- /codes/cpp/chap10/code_10-01.cpp: -------------------------------------------------------------------------------- 1 | // 이하의 프로그램에서는 X[0]=0, X[N+1]=W를 가정한다 2 | dp[0] = 1; 3 | for (int i = 1; i <= N + 1; i++) { 4 | for (int j = 0; j < i; j++) { 5 | // if문의 조건식은 '징검다리 j로부터 징검다리 i로 직접 점프할 수 있는가?'를 판정한다 6 | if (X[i] - R <= X[j] && X[j] <= X[i] - L) dp[i] += dp[j]; 7 | dp[i] %= 1000000007; 8 | } 9 | } 10 | 11 | // 답을 출력 12 | cout << dp[N + 1] << endl; 13 | -------------------------------------------------------------------------------- /codes/java/chap06/answer_A36.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int K = sc.nextInt(); 10 | 11 | // 출력 12 | if (K >= 2*N-2 && K%2 == 0) System.out.println("Yes"); 13 | else System.out.println("No"); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /editorial/chap01/python/answer_B03.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | A = list(map(int, input().split())) 4 | 5 | # 답을 구한다 6 | Answer = False 7 | for i in range(N): 8 | for j in range(i+1, N): 9 | for k in range(j+1, N): 10 | if A[i] + A[j] + A[k] == 1000: 11 | Answer = True 12 | 13 | # 출력 14 | if Answer == True: 15 | print("Yes") 16 | else: 17 | print("No") 18 | -------------------------------------------------------------------------------- /editorial/chap06/python/answer_B41.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | X, Y = map(int, input().split()) 3 | 4 | # 거꾸로 생각하기 5 | Answer = [] 6 | while X>=2 or Y>=2: 7 | Answer.append([X, Y]) 8 | if X > Y: 9 | X -= Y 10 | else: 11 | Y -= X 12 | Answer.reverse() 13 | 14 | # 출력 15 | print(len(Answer)) 16 | for i in range(len(Answer)): 17 | print(str(Answer[i][0]) + ' ' + str(Answer[i][1])) 18 | -------------------------------------------------------------------------------- /codes/cpp/chap01/answer_A04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | // 입력 6 | int N; 7 | cin >> N; 8 | 9 | // 윗자리부터 순서대로 '2진법으로 변환한 값'을 구한다 10 | for (int x = 9; x >= 0; x--) { 11 | int wari = (1 << x); // 2의 x제곱 12 | cout << (N / wari) % 2; // 나눗셈의 결과에 따라 0 또는 1을 출력 13 | } 14 | cout << endl; // 마지막에 줄바꿈한다 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /editorial/chap03/python/answer_B12.py: -------------------------------------------------------------------------------- 1 | def f(x): 2 | return x*x*x + x 3 | 4 | N = int(input()) 5 | 6 | # 바이너리 서치 7 | Left = 0.0 8 | Right = 100.0 9 | for i in range(20): 10 | Mid = (Left + Right) / 2 11 | val = f(Mid) 12 | 13 | # 탐색 범위 좁히기 14 | if val > N: 15 | Right = Mid # 왼쪽 절반으로 쪼개진다 16 | else: 17 | Left = Mid # 오른쪽 절반으로 쪼개진다 18 | 19 | # 출력 20 | print(Mid) 21 | -------------------------------------------------------------------------------- /editorial/chap05/python/answer_B34.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, X, Y = map(int, input().split()) 3 | A = list(map(int, input().split())) 4 | 5 | # Grundy 수 계산 6 | XOR_Sum = 0 7 | for i in range(N): 8 | Grundy = [0, 0, 1, 1, 2] # 5로 나눈 나머지 Grundy 수에 대응하는 Grundy 수 9 | XOR_Sum ^= Grundy[A[i] % 5] 10 | 11 | # 출력 12 | if XOR_Sum != 0: 13 | print("First") 14 | else: 15 | print("Second") 16 | -------------------------------------------------------------------------------- /codes/cpp/chap09/code_9-04.cpp: -------------------------------------------------------------------------------- 1 | // dist[i]의 값은 ∞ 대신 매우 큰 값으로 설정 2 | dist[1] = 0; 3 | for (int i = 2; i <= N; i++) dist[i] = 1000000000; 4 | 5 | // 벨만-포드 알고리즘 6 | for (int i = 1; i <= N - 1; i++) { 7 | for (int j = 1; j <= M; j++) { 8 | dist[B[j]] = min(dist[B[j]], dist[A[j]] + C[j]); 9 | } 10 | } 11 | 12 | // 답을 출력 13 | for (int i = 1; i <= N; i++) cout << dist[i] << endl; 14 | -------------------------------------------------------------------------------- /codes/python/chap02/answer_A06.py: -------------------------------------------------------------------------------- 1 | N, Q = map(int, input().split()) 2 | A = list(map(int, input().split())) 3 | L = [ None ] * Q 4 | R = [ None ] * Q 5 | for j in range(Q): 6 | L[j], R[j] = map(int, input().split()) 7 | 8 | S = [ None ] * (N + 1) 9 | S[0] = 0 10 | for i in range(N): 11 | S[i + 1] = S[i] + A[i] 12 | 13 | for j in range(Q): 14 | print(S[R[j]] - S[L[j] - 1]) 15 | -------------------------------------------------------------------------------- /codes/python/chap06/answer_A41.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | S = input() 4 | 5 | # 답을 구한다 6 | Answer = False 7 | for i in range(0, N-2): 8 | if S[i] == 'R' and S[i+1] == 'R' and S[i+2] == 'R': 9 | Answer = True 10 | if S[i] == 'B' and S[i+1] == 'B' and S[i+2] == 'B': 11 | Answer = True 12 | 13 | # 출력 14 | if Answer == True: 15 | print("Yes") 16 | else: 17 | print("No") 18 | -------------------------------------------------------------------------------- /editorial/chap03/python/answer_B11.py: -------------------------------------------------------------------------------- 1 | import bisect 2 | 3 | # 입력 4 | N = int(input()) 5 | A = list(map(int, input().split())) 6 | Q = int(input()) 7 | X = [ None ] * Q 8 | for i in range(Q): 9 | X[i] = int(input()) 10 | 11 | # 배열 X 정렬 12 | A.sort() 13 | 14 | # 질문에 답한다(배열 A는 0번부터 시작한다는 점에 유의하세요!) 15 | for i in range(Q): 16 | pos1 = bisect.bisect_left(A, X[i]) 17 | print(pos1) 18 | -------------------------------------------------------------------------------- /codes/python/chap05/answer_A29.py: -------------------------------------------------------------------------------- 1 | # a의 b제곱을 m으로 나눈 나머지를 반환하는 함수 2 | def Power(a, b, m): 3 | p = a 4 | Answer = 1 5 | for i in range(30): 6 | wari = 2 ** i 7 | if (b // wari) % 2 == 1: 8 | Answer = (Answer * p) % m # a의 2^i 제곱을 곱할 때 9 | p = (p * p) % m 10 | return Answer 11 | 12 | # 입력 13 | a, b = map(int, input().split()) 14 | 15 | # 출력 16 | print(Power(a, b, 1000000007)) 17 | -------------------------------------------------------------------------------- /editorial/chap05/answer_B29.py: -------------------------------------------------------------------------------- 1 | # a의 b제곱을 m으로 나눈 나머지를 반환하는 함수 2 | def Power(a, b, m): 3 | p = a 4 | Answer = 1 5 | for i in range(60): 6 | wari = 2 ** i 7 | if (b // wari) % 2 == 1: 8 | Answer = (Answer * p) % m # a의 2^i 제곱을 곱할 때 9 | p = (p * p) % m 10 | return Answer 11 | 12 | # 입력 13 | a, b = map(int, input().split()) 14 | 15 | # 출력 16 | print(Power(a, b, 1000000007)) 17 | -------------------------------------------------------------------------------- /codes/cpp/chap10/code_10-02.cpp: -------------------------------------------------------------------------------- 1 | // 점수의 최댓값이 12 이상인지를 판정하고자 하는 경우, check(12)를 호출하면 된다 2 | bool check(int x) { 3 | int Count = 0, Last_Kireme = 0; // Count는 현 시점에서 몇 번 잘랐는가를 나타낸다 4 | for (int i = 1; i <= N; i++) { 5 | if (A[i] - Last_Kireme >= x && L - A[i] >= x) { 6 | Count += 1; 7 | Last_Kireme = A[i]; 8 | } 9 | } 10 | if (Count >= K) return true; 11 | return false; 12 | } 13 | -------------------------------------------------------------------------------- /editorial/chap05/answer_B26.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | 4 | # 엘라토스테네스의 체 5 | # 정수 x가 지워진 경우에 한해 Deleted[x]=true 6 | Deleted = [ False ] * 1000009 7 | LIMIT = int(N ** 0.5) 8 | for i in range(2, LIMIT+1): 9 | if Deleted[i] == False: 10 | for j in range(i*2, N+1, i): 11 | Deleted[j] = True 12 | 13 | # 답을 출력 14 | for i in range(2, N+1): 15 | if Deleted[i] == False: 16 | print(i) 17 | -------------------------------------------------------------------------------- /editorial/chap05/python/answer_B29.py: -------------------------------------------------------------------------------- 1 | # a의 b제곱을 m으로 나눈 나머지를 반환하는 함수 2 | def Power(a, b, m): 3 | p = a 4 | Answer = 1 5 | for i in range(60): 6 | wari = 2 ** i 7 | if (b // wari) % 2 == 1: 8 | Answer = (Answer * p) % m # a의 2^i 제곱을 곱할 때 9 | p = (p * p) % m 10 | return Answer 11 | 12 | # 입력 13 | a, b = map(int, input().split()) 14 | 15 | # 출력 16 | print(Power(a, b, 1000000007)) 17 | -------------------------------------------------------------------------------- /codes/python/chap03/answer_A15.py: -------------------------------------------------------------------------------- 1 | import bisect 2 | 3 | # 입력 4 | N = int(input()) 5 | A = list(map(int, input().split())) 6 | 7 | # 배열 T 작성(중복 제거) 8 | T = list(set(A)) 9 | T.sort() 10 | 11 | # 답을 구한다 12 | B = [ None ] * N 13 | for i in range(N): 14 | B[i] = bisect.bisect_left(T, A[i]) 15 | B[i] += 1 16 | 17 | # 답을 공백으로 구분해서 출력 18 | Answer = [str(i) for i in B] 19 | print(" ".join(Answer)) 20 | -------------------------------------------------------------------------------- /codes/python/chap08/answer_A51.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | # 입력 4 | Q = int(input()) # 쿼리 개수 5 | queries = [ input().split() for i in range(Q) ] # 쿼리 정보(각 요소는 ["1", 제목을 나타내는 문자열] or ["2"] or ["3"]이다.) 6 | 7 | # 쿼리 처리 8 | S = deque() 9 | for q in queries: 10 | if q[0] == "1": 11 | S.append(q[1]) 12 | if q[0] == "2": 13 | print(S[-1]) 14 | if q[0] == "3": 15 | S.pop() -------------------------------------------------------------------------------- /codes/python/chap08/answer_A52.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | # 입력 4 | Q = int(input()) # 쿼리 개수 5 | queries = [ input().split() for i in range(Q) ] # 쿼리 정보(각 요소는 ["1", 이름을 나타내는 문자열] or ["2"] or ["3"]이다.) 6 | 7 | # 쿼리 처리 8 | T = deque() 9 | for q in queries: 10 | if q[0] == "1": 11 | T.append(q[1]) 12 | if q[0] == "2": 13 | print(T[0]) 14 | if q[0] == "3": 15 | T.popleft() -------------------------------------------------------------------------------- /editorial/chap05/answer_B28.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int mod = 1000000007; 5 | int N, a[10000009]; 6 | 7 | int main() { 8 | // 입력 9 | cin >> N; 10 | 11 | // 피보나치 수열 계산 12 | a[1] = 1; 13 | a[2] = 1; 14 | for (int i = 3; i <= N; i++) { 15 | a[i] = (a[i - 1] + a[i - 2]) % mod; 16 | } 17 | 18 | // 출력 19 | cout << a[N] << endl; 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /editorial/chap05/cpp/answer_B28.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int mod = 1000000007; 5 | int N, a[10000009]; 6 | 7 | int main() { 8 | // 입력 9 | cin >> N; 10 | 11 | // 피보나치 수열 계산 12 | a[1] = 1; 13 | a[2] = 1; 14 | for (int i = 3; i <= N; i++) { 15 | a[i] = (a[i - 1] + a[i - 2]) % mod; 16 | } 17 | 18 | // 출력 19 | cout << a[N] << endl; 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /editorial/chap05/python/answer_B26.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | 4 | # 엘라토스테네스의 체 5 | # 정수 x가 지워진 경우에 한해 Deleted[x]=true 6 | Deleted = [ False ] * 1000009 7 | LIMIT = int(N ** 0.5) 8 | for i in range(2, LIMIT+1): 9 | if Deleted[i] == False: 10 | for j in range(i*2, N+1, i): 11 | Deleted[j] = True 12 | 13 | # 답을 출력 14 | for i in range(2, N+1): 15 | if Deleted[i] == False: 16 | print(i) 17 | -------------------------------------------------------------------------------- /editorial/final/cpp/answer_C05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | // 입력 6 | int N; 7 | cin >> N; N -= 1; 8 | 9 | // 출력 10 | for (int x = 9; x >= 0; x--) { 11 | int wari = (1 << x); 12 | if ((N / wari) % 2 == 0) cout << "4"; // 2진법 0이 4에 대응 13 | if ((N / wari) % 2 == 1) cout << "7"; // 2진법의 1이 7에 대응 14 | } 15 | cout << endl; 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /codes/cpp/chap07/code_7-14.cpp: -------------------------------------------------------------------------------- 1 | // 01 // A[Left], A[Left+1], …, A[Right-1]의 최댓값을 구하는 함수 2 | int GetMax(int Left, int Right) { 3 | // 구간에 포함된 요소가 1개가 된 경우 4 | if (Right - Left == 1) return A[Left]; 5 | // 왼쪽 반과 오른쪽 반을 분할한다 6 | int Mid = (Left + Right) / 2; 7 | int res1 = GetMax(Left, Mid); // res1은 '왼쪽 반의 최댓값' 8 | int res2 = GetMax(Mid, Right); // res2는 '오른쪽 반의 최댓값' 9 | return max(res1, res2); 10 | } 11 | -------------------------------------------------------------------------------- /codes/java/chap05/answer_A31.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | long N = sc.nextLong(); 8 | long A1 = N / 3; // 3으로 나누어떨어지는 수의 개수 9 | long A2 = N / 5; // 5로 나누어떨어지는 수의 개수 10 | long A3 = N / 15; // 3, 5 모두로 나누어떨어지는 수(= 15의 배수)의 개수 11 | System.out.println(A1 + A2 - A3); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /codes/python/chap06/answer_A43.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, L = map(int, input().split()) 3 | A = [ None ] * N 4 | B = [ None ] * N 5 | for i in range(N): 6 | A[i], B[i] = input().split() 7 | A[i] = int(A[i]) 8 | 9 | # 답을 구한다 10 | Answer = 0 11 | for i in range(N): 12 | if B[i] == 'E': 13 | Answer = max(Answer, L - A[i]) 14 | if B[i] == 'W': 15 | Answer = max(Answer, A[i]) 16 | 17 | # 출력 18 | print(Answer) 19 | -------------------------------------------------------------------------------- /editorial/chap01/cpp/answer_B02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | // 입력 6 | int A, B; 7 | cin >> A >> B; 8 | 9 | // 답을 구한다 10 | bool Answer = false; 11 | for (int i = A; i <= B; i++) { 12 | if (100 % i == 0) Answer = true; 13 | } 14 | 15 | // 출력 16 | if (Answer == true) cout << "Yes" << endl; 17 | else cout << "No" << endl; 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /codes/python/chap04/answer_A22.py: -------------------------------------------------------------------------------- 1 | # 입력(배열 A, B는 0번부터 시작한다는 점에 주의!) 2 | N = int(input()) 3 | A = list(map(int, input().split())) 4 | B = list(map(int, input().split())) 5 | 6 | # 배열 초기화 7 | dp = [ -(10 ** 9) ] * (N + 1) 8 | dp[1] = 0 9 | 10 | # 동적 계획 알고리즘 11 | for i in range(1, N): 12 | dp[A[i-1]] = max(dp[A[i-1]], dp[i] + 100) 13 | dp[B[i-1]] = max(dp[B[i-1]], dp[i] + 150) 14 | 15 | # 출력 16 | print(dp[N]) 17 | -------------------------------------------------------------------------------- /codes/python/chap01/answer_A03.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, K = map(int, input().split()) 3 | P = list(map(int, input().split())) 4 | Q = list(map(int, input().split())) 5 | Answer = False 6 | 7 | # 완전 탐색(Answer는 '합계가 K가 되는 선택 방법을 발견했는가'를 나타냄) 8 | for x in range(N): 9 | for y in range(N): 10 | if P[x] + Q[y] == K: 11 | Answer = True 12 | 13 | # 출력 14 | if Answer == True: 15 | print("Yes") 16 | else: 17 | print("No") 18 | -------------------------------------------------------------------------------- /editorial/chap06/python/answer_B40.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | A = list(map(int, input().split())) 4 | 5 | # 개수를 센다 6 | cnt = [ 0 ] * 100 7 | for i in range(N): 8 | cnt[A[i] % 100] += 1 9 | 10 | # 답을 구한다 11 | Answer = 0 12 | for i in range(1, 50): 13 | Answer += cnt[i] * cnt[100-i] 14 | Answer += cnt[0] * (cnt[0] - 1) // 2 15 | Answer += cnt[50] * (cnt[50] - 1) // 2 16 | 17 | # 출력 18 | print(Answer) 19 | -------------------------------------------------------------------------------- /codes/cpp/chap01/answer_A05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | // 입력 6 | int N, K, Answer = 0; 7 | cin >> N >> K; 8 | 9 | // 완전 탐색 10 | for (int x = 1; x <= N; x++) { 11 | for (int y = 1; y <= N; y++) { 12 | int z = K - x - y; // 흰 카드에 적혀야 하는 정수 13 | if (z >= 1 && z <= N) Answer += 1; 14 | } 15 | } 16 | 17 | // 출력 18 | cout << Answer << endl; 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /codes/cpp/chap01/code_1-02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | // 입력 6 | int N, K, Answer = 0; 7 | cin >> N >> K; 8 | 9 | // 완전 탐색 10 | for (int x = 1; x <= N; x++) { 11 | for (int y = 1; y <= N; y++) { 12 | for (int z = 1; z <= N; z++) { 13 | if (x + y + z == K) Answer += 1; 14 | } 15 | } 16 | } 17 | 18 | // 출력 19 | cout << Answer << endl; 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /codes/cpp/chap03/code_3-01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main() { 6 | // 입력 7 | int N, A[100009]; 8 | cin >> N; 9 | for (int i = 1; i <= N; i++) cin >> A[i]; 10 | 11 | // 배열 정렬 12 | // 여기에서 함수 sort(A+L, A+R)에서는 A[L]부터 A[R-1]까지의 부분을 정렬한다 13 | sort(A + 1, A + N + 1); 14 | 15 | // 출력 16 | for (int i = 1; i <= N; i++) cout << A[i] << endl; 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /codes/cpp/chap05/code_5-05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // a의 b제곱을 m으로 나눈 나머지를 반환하는 함수 5 | long long Power(long long a, long long b, long long m) { 6 | long long Answer = 1; 7 | for (int i = 1; i <= b; i++) Answer = (Answer * a) % m; 8 | return Answer; 9 | } 10 | 11 | int main() { 12 | long long a, b; 13 | cin >> a >> b; 14 | cout << Power(a, b, 1000000007) << endl; 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /editorial/chap05/answer_B33.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, H, W = map(int, input().split()) 3 | A = [ None ] * N 4 | B = [ None ] * N 5 | for i in range(N): 6 | A[i], B[i] = map(int, input().split()) 7 | 8 | # 전부 XOR한 값(Nim sum)을 구한다 9 | XOR_Sum = 0 10 | for i in range(N): 11 | XOR_Sum = (XOR_Sum ^ (A[i]-1)) 12 | XOR_Sum = (XOR_Sum ^ (B[i]-1)) 13 | 14 | # 출력 15 | if XOR_Sum != 0: 16 | print("First") 17 | else: 18 | print("Second") 19 | -------------------------------------------------------------------------------- /editorial/chap05/python/answer_B33.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, H, W = map(int, input().split()) 3 | A = [ None ] * N 4 | B = [ None ] * N 5 | for i in range(N): 6 | A[i], B[i] = map(int, input().split()) 7 | 8 | # 전부 XOR한 값(Nim sum)을 구한다 9 | XOR_Sum = 0 10 | for i in range(N): 11 | XOR_Sum = (XOR_Sum ^ (A[i]-1)) 12 | XOR_Sum = (XOR_Sum ^ (B[i]-1)) 13 | 14 | # 출력 15 | if XOR_Sum != 0: 16 | print("First") 17 | else: 18 | print("Second") 19 | -------------------------------------------------------------------------------- /editorial/chap04/python/answer_B22.py: -------------------------------------------------------------------------------- 1 | # 입력(A, B가 0번부터 시작하는 것에 주의) 2 | N = int(input()) 3 | A = list(map(int, input().split())) 4 | B = list(map(int, input().split())) 5 | 6 | # 배열 dp 초기화 7 | dp = [ 2000000000 ] * N 8 | dp[0] = 0 9 | 10 | # 동적 계획 알고리즘 11 | for i in range(N): 12 | if i <= N-2: 13 | dp[i+1] = min(dp[i+1], dp[i] + A[i]) 14 | if i <= N-3: 15 | dp[i+2] = min(dp[i+2], dp[i] + B[i]) 16 | 17 | # 출력 18 | print(dp[N-1]) 19 | -------------------------------------------------------------------------------- /codes/cpp/chap05/answer_A27.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int GCD(int A, int B) { 5 | while (A >= 1 && B >= 1) { 6 | if (A >= B) { 7 | A = (A % B); // A의 값을 변경하는 경우 8 | } 9 | else { 10 | B = (B % A); // B의 값을 변경하는 경우 11 | } 12 | } 13 | if (A != 0) return A; 14 | return B; 15 | } 16 | 17 | int main() { 18 | int A, B; 19 | cin >> A >> B; 20 | cout << GCD(A, B) << endl; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /editorial/chap05/answer_B27.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int GCD(int A, int B) { 5 | while (A >= 1 && B >= 1) { 6 | if (A >= B) { 7 | A = (A % B); // A의 값을 변경하는 경우 8 | } 9 | else { 10 | B = (B % A); // B의 값을 변경하는 경우 11 | } 12 | } 13 | if (A != 0) return A; 14 | return B; 15 | } 16 | 17 | int main() { 18 | long long A, B; 19 | cin >> A >> B; 20 | cout << A * B / GCD(A, B) << endl; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /codes/java/chap01/answer_A04.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | 10 | // 윗자리부터 순서대로 '2진법으로 변환한 값'을 구한다 11 | for (int x = 9; x >= 0; x--) { 12 | int wari = (1 << x); // 2의 x제곱 13 | System.out.print((N / wari) % 2); // 분할 결과에 따라 0 또는 1 출력 14 | } 15 | System.out.println(); // 마지막에 줄바꿈한다 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /codes/python/chap05/answer_A26.py: -------------------------------------------------------------------------------- 1 | # x가 소수일 때 true, 소수가 아닐 때 false를 반환한다 2 | def isPrime(N): 3 | LIMIT = int(N ** 0.5) 4 | for i in range(2, LIMIT + 1): 5 | if N % i == 0: 6 | return False 7 | return True 8 | 9 | # 입력 10 | Q = int(input()) 11 | X = [ None ] * Q 12 | for i in range(Q): 13 | X[i] = int(input()) 14 | 15 | # 출력 16 | for i in range(Q): 17 | Answer = isPrime(X[i]) 18 | if Answer == True: 19 | print("Yes") 20 | else: 21 | print("No") 22 | -------------------------------------------------------------------------------- /codes/python/chap05/answer_A32.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, A, B = map(int, input().split()) 3 | 4 | # 배열 dp 정의 5 | # dp[x]=True일 때 승리 상태, dp[x]=False일 때 패배 상태 6 | dp = [ None ] * (N+1) 7 | 8 | # 승자를 계산한다 9 | for i in range(N+1): 10 | if i >= A and dp[i-A] == False: 11 | dp[i] = True 12 | elif i >= B and dp[i-B] == False: 13 | dp[i] = True 14 | else: 15 | dp[i] = False 16 | 17 | # 출력 18 | if dp[N] == True: 19 | print("First") 20 | else: 21 | print("Second") 22 | -------------------------------------------------------------------------------- /editorial/chap05/cpp/answer_B27.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int GCD(int A, int B) { 5 | while (A >= 1 && B >= 1) { 6 | if (A >= B) { 7 | A = (A % B); // A의 값을 변경하는 경우 8 | } 9 | else { 10 | B = (B % A); // B의 값을 변경하는 경우 11 | } 12 | } 13 | if (A != 0) return A; 14 | return B; 15 | } 16 | 17 | int main() { 18 | long long A, B; 19 | cin >> A >> B; 20 | cout << A * B / GCD(A, B) << endl; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /codes/cpp/chap05/answer_A33.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, A[100009]; 5 | 6 | int main() { 7 | // 입력 8 | cin >> N; 9 | for (int i = 1; i <= N; i++) cin >> A[i]; 10 | 11 | // 전부 XOR한 값(Nim sum)을 구한다 12 | int XOR_Sum = A[1]; 13 | for (int i = 2; i <= N; i++) XOR_Sum = (XOR_Sum ^ A[i]); 14 | 15 | // 출력 16 | if (XOR_Sum != 0) cout << "First" << endl; 17 | if (XOR_Sum == 0) cout << "Second" << endl; 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /editorial/chap05/answer_B32.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, K = map(int, input().split()) 3 | A = list(map(int, input().split())) 4 | 5 | # 승자를 계산한다 6 | # 배열 dp에 대해: dp[x]=true일 때 승리 상태, dp[x]=false일 때 패배 상태 7 | dp = [ None ] * (N + 1) 8 | for i in range(N+1): 9 | dp[i] = False 10 | for j in range(K): 11 | if i>=A[j] and dp[i-A[j]]==False: 12 | dp[i] = True # 패배 상태로 전환할 수 있다면, 승리 상태 13 | 14 | # 출력 15 | if dp[N] == True: 16 | print("First") 17 | else: 18 | print("Second") 19 | -------------------------------------------------------------------------------- /editorial/chap08/cpp/answer_B54.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, A[100009]; 6 | map Map; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N; 11 | for (int i = 1; i <= N; i++) cin >> A[i]; 12 | 13 | // 답을 구한다 14 | long long Answer = 0; 15 | for (int i = 1; i <= N; i++) { 16 | Answer += Map[A[i]]; 17 | Map[A[i]] += 1; 18 | } 19 | 20 | // 출력 21 | cout << Answer << endl; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /editorial/final/cpp/answer_C02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, A[109]; 6 | int Answer = 0; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N; 11 | for (int i = 1; i <= N; i++) cin >> A[i]; 12 | 13 | // 답을 구한다(완전 탐색) 14 | for (int i = 1; i <= N; i++) { 15 | for (int j = i + 1; j <= N; j++) Answer = max(Answer, A[i] + A[j]); 16 | } 17 | 18 | // 출력 19 | cout << Answer << endl; 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /editorial/chap05/answer_B31.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | 4 | # 계산 5 | A1 = (N // 3); # 3으로 나누어떨어지는 수의 개수 6 | A2 = (N // 5); # 5로 나누어떨어지는 수의 개수 7 | A3 = (N // 7); # 5로 나누어떨어지는 수의 개수 8 | A4 = (N // 15); # 3, 5로 나누어떨어지는 수(= 15의 배수)의 개수 9 | A5 = (N // 21); # 3, 7로 나누어떨어지는 수(= 21의 배수)의 개수 10 | A6 = (N // 35); # 5, 7로 나누어떨어지는 수(= 35의 배수)의 개수 11 | A7 = (N // 105); # 3, 5, 7로 나누어떨어지는 수(= 105의 배수)의 개수 12 | 13 | # 출력 14 | print(A1 + A2 + A3 - A4 - A5 - A6 + A7) 15 | -------------------------------------------------------------------------------- /codes/python/chap06/answer_A39.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | # A는 (종료 시각, 시작 시각)으로 되어 있음에 주의 [종료 시각의 오름차순으로 정렬하기 위함]. 3 | N = int(input()) 4 | A = [] 5 | for i in range(N): 6 | l, r = map(int, input().split()) 7 | A.append([r, l]) 8 | 9 | # 정렬 10 | A.sort() 11 | 12 | # 종료 시각이 빠른 것부터 탐욕적으로 취해 간다(CurrentTime은 현재 시각) 13 | CurrentTime = 0 14 | Answer = 0 15 | for i in range(N): 16 | if CurrentTime <= A[i][1]: 17 | CurrentTime = A[i][0] 18 | Answer += 1 19 | 20 | # 출력 21 | print(Answer) 22 | -------------------------------------------------------------------------------- /editorial/chap05/python/answer_B31.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | 4 | # 계산 5 | A1 = (N // 3); # 3으로 나누어떨어지는 수의 개수 6 | A2 = (N // 5); # 5로 나누어떨어지는 수의 개수 7 | A3 = (N // 7); # 5로 나누어떨어지는 수의 개수 8 | A4 = (N // 15); # 3, 5로 나누어떨어지는 수(= 15의 배수)의 개수 9 | A5 = (N // 21); # 3, 7로 나누어떨어지는 수(= 21의 배수)의 개수 10 | A6 = (N // 35); # 5, 7로 나누어떨어지는 수(= 35의 배수)의 개수 11 | A7 = (N // 105); # 3, 5, 7로 나누어떨어지는 수(= 105의 배수)의 개수 12 | 13 | # 출력 14 | print(A1 + A2 + A3 - A4 - A5 - A6 + A7) 15 | -------------------------------------------------------------------------------- /editorial/chap05/python/answer_B32.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, K = map(int, input().split()) 3 | A = list(map(int, input().split())) 4 | 5 | # 승자를 계산한다 6 | # 배열 dp에 대해: dp[x]=true일 때 승리 상태, dp[x]=false일 때 패배 상태 7 | dp = [ None ] * (N + 1) 8 | for i in range(N+1): 9 | dp[i] = False 10 | for j in range(K): 11 | if i>=A[j] and dp[i-A[j]]==False: 12 | dp[i] = True # 패배 상태로 전환할 수 있다면, 승리 상태 13 | 14 | # 출력 15 | if dp[N] == True: 16 | print("First") 17 | else: 18 | print("Second") 19 | -------------------------------------------------------------------------------- /editorial/chap06/cpp/answer_B36.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, K; 6 | string S; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N >> K; 11 | cin >> S; 12 | 13 | // ON으로 되어 있는 것의 개수를 센다 14 | int numON = 0; 15 | for (int i = 0; i < N; i++) { 16 | if (S[i] == '1') numON += 1; 17 | } 18 | 19 | // 답을 출력 20 | if (numON % 2 == K % 2) cout << "Yes" << endl; 21 | else cout << "No" << endl; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /editorial/chap08/python/answer_B57.py: -------------------------------------------------------------------------------- 1 | dp = [[0] * 300009 for _ in range(30)] 2 | 3 | # 입력 4 | N, K = map(int, input().split()) 5 | 6 | # 1 회 조작 후 값 구하기 7 | for i in range(N + 1): 8 | dp[0][i] = i - sum(map(int, str(i))) 9 | 10 | # 사전 계산 11 | for d in range(29): 12 | for i in range(N + 1): 13 | dp[d + 1][i] = dp[d][dp[d][i]] 14 | 15 | # 답을 구한다 16 | for num in range(1, N + 1): 17 | for d in range(30): 18 | if K & (1 << d): 19 | num = dp[d][num] 20 | print(num) 21 | -------------------------------------------------------------------------------- /codes/cpp/chap08/code_8-06.cpp: -------------------------------------------------------------------------------- 1 | // u는 현재 셀 번호, [a, b)는 셀에 대응하는 반개구간, [l, r)은 구할 반개구간 2 | // 반개구간 [l, r)의 최댓값을 구하려면 query(l, r, 1, siz+1, 1)을 호출하면 된다 3 | int query(int l, int r, int a, int b, int u) { 4 | if (r <= a || b <= l) return -1000000000; // 전혀 포함되지 않는 경우 5 | if (l <= a && b <= r) return dat[u]; // 완전히 포함되는 경우 6 | int m = (a + b) / 2; 7 | int AnswerL = query(l, r, a, m, u * 2); 8 | int AnswerR = query(l, r, m, b, u * 2 + 1); 9 | return max(AnswerL, AnswerR); 10 | } 11 | -------------------------------------------------------------------------------- /codes/python/chap06/answer_A45.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, C = input().split() 3 | A = input() 4 | N = int(N) 5 | 6 | # 점수 계산 7 | score = 0 8 | for i in range(N): 9 | if A[i] == 'W': 10 | score += 0 11 | if A[i] == 'B': 12 | score += 1 13 | if A[i] == 'R': 14 | score += 2 15 | 16 | # 출력 17 | if score%3 == 0 and C == 'W': 18 | print("Yes") 19 | elif score%3 == 1 and C == 'B': 20 | print("Yes") 21 | elif score%3 == 2 and C == 'R': 22 | print("Yes") 23 | else: 24 | print("No") 25 | -------------------------------------------------------------------------------- /codes/cpp/chap01/answer_A02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, X, A[109]; 5 | bool Answer = false; 6 | 7 | int main() { 8 | // 입력 9 | cin >> N >> X; 10 | for (int i = 1; i <= N; i++) cin >> A[i]; 11 | 12 | // 완전 탐색(변수 Answer는 '기존에 x를 발견했는가'를 나타냄) 13 | for (int i = 1; i <= N; i++) { 14 | if (A[i] == X) Answer = true; 15 | } 16 | 17 | // 출력 18 | if (Answer == true) cout << "Yes" << endl; 19 | else cout << "No" << endl; 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /codes/python/chap06/answer_A38.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | D, N = map(int, input().split()) 3 | L = [ None ] * N 4 | R = [ None ] * N 5 | H = [ None ] * N 6 | for i in range(N): 7 | L[i], R[i], H[i] = map(int, input().split()) 8 | 9 | # 배열 초기화(1일은 24시간) 10 | LIM = [ 24 ] * (D + 1) 11 | 12 | # 상한 값을 구한다 13 | for i in range(N): 14 | for j in range(L[i], R[i]+1): 15 | LIM[j] = min(LIM[j], H[i]) 16 | 17 | # 답을 출력 18 | Answer = 0 19 | for i in range(1, D+1): 20 | Answer += LIM[i] 21 | print(Answer) 22 | -------------------------------------------------------------------------------- /editorial/chap08/python/answer_B52.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | 4 | # 입력 5 | N, X = map(int, input().split()) 6 | X -= 1 7 | A = list(input()) 8 | 9 | # 시뮬레이션 10 | Q = deque([X]) 11 | Q.append(X) 12 | A[X] = '@' 13 | while Q: 14 | pos = Q.popleft() 15 | if pos - 1 >= 0 and A[pos - 1] == '.': 16 | A[pos - 1] = '@' 17 | Q.append(pos - 1) 18 | if pos + 1 < N and A[pos + 1] == '.': 19 | A[pos + 1] = '@' 20 | Q.append(pos + 1) 21 | 22 | # 출력 23 | print("".join(A)) 24 | -------------------------------------------------------------------------------- /editorial/chap01/cpp/answer_B04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main() { 6 | // 입력 7 | string N; 8 | cin >> N; 9 | 10 | // 답을 구한다 11 | int Answer = 0; 12 | for (int i = 0; i < N.size(); i++) { 13 | int keta; 14 | int kurai = (1 << (N.size() - 1 - i)); 15 | if (N[i] == '0') keta = 0; 16 | if (N[i] == '1') keta = 1; 17 | Answer += keta * kurai; 18 | } 19 | 20 | // 출력 21 | cout << Answer << endl; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /editorial/chap06/cpp/answer_B43.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, M; 5 | int A[200009]; 6 | int Incorrect[200009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N >> M; 11 | for (int i = 1; i <= M; i++) cin >> A[i]; 12 | 13 | // 오답 수 구하기 14 | for (int i = 1; i <= N; i++) Incorrect[i] = 0; 15 | for (int i = 1; i <= M; i++) Incorrect[A[i]] += 1; 16 | 17 | // 답을 출력 18 | for (int i = 1; i <= N; i++) cout << M - Incorrect[i] << endl; 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /editorial/chap08/cpp/answer_B51.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main() { 6 | // 입력 7 | string S; 8 | cin >> S; 9 | 10 | // 왼쪽부터 순서대로 살펴본다 11 | // 문자열은 0번째 문자부터 시작한다는 점에 유의하세요. 12 | stack Stack; 13 | for (int i = 0; i < S.size(); i++) { 14 | if (S[i] == '(') { 15 | Stack.push(i + 1); 16 | } 17 | if (S[i] == ')') { 18 | cout << Stack.top() << " " << i + 1 << endl; 19 | Stack.pop(); 20 | } 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /codes/python/chap02/answer_A07.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | D = int(input()) 3 | N = int(input()) 4 | L = [ None ] * N 5 | R = [ None ] * N 6 | for i in range(N): 7 | L[i], R[i] = map(int, input().split()) 8 | 9 | # 전일 비에 더한다 10 | B = [ 0 ] * (D+2) 11 | for i in range(N): 12 | B[L[i]] += 1 13 | B[R[i]+1] -= 1 14 | 15 | # 누적 합을 구한다 16 | Answer = [ None ] * (D+2) 17 | Answer[0] = 0 18 | for d in range(1, D+1): 19 | Answer[d] = Answer[d - 1] + B[d] 20 | 21 | # 출력 22 | for d in range(1, D+1): 23 | print(Answer[d]) 24 | -------------------------------------------------------------------------------- /codes/cpp/chap05/code_5-04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | // 입력 6 | long long N, A[100009]; char T[100009]; 7 | cin >> N; 8 | for (int i = 1; i <= N; i++) cin >> T[i] >> A[i]; 9 | 10 | // 출력(Answer는 현재 칠판의 수) 11 | long long Answer = 0; 12 | for (int i = 1; i <= N; i++) { 13 | if (T[i] == '+') Answer += A[i]; 14 | if (T[i] == '-') Answer -= A[i]; 15 | if (T[i] == '*') Answer *= A[i]; 16 | cout << Answer % 10000 << endl; 17 | } 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /codes/cpp/chap06/answer_A43.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, L; 6 | int A[200009]; char B[200009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N >> L; 11 | for (int i = 1; i <= N; i++) cin >> A[i] >> B[i]; 12 | 13 | // 답을 구한다 14 | int Answer = 0; 15 | for (int i = 1; i <= N; i++) { 16 | if (B[i] == 'E') Answer = max(Answer, L - A[i]); 17 | if (B[i] == 'W') Answer = max(Answer, A[i]); 18 | } 19 | cout << Answer << endl; 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /editorial/chap02/python/answer_B07.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | T = int(input()) 3 | N = int(input()) 4 | L = [ None ] * N 5 | R = [ None ] * N 6 | for i in range(N): 7 | L[i], R[i] = map(int, input().split()) 8 | 9 | # "이전 시간과의 차이"에 추가 10 | B = [ 0 ] * (T + 1) 11 | for i in range(N): 12 | B[L[i]] += 1 13 | B[R[i]] -= 1 14 | 15 | # 누적 합을 구한다 16 | Answer = [ None ] * (T + 1) 17 | Answer[0] = B[0] 18 | for d in range(1, T+1): 19 | Answer[d] = Answer[d-1] + B[d] 20 | 21 | # 출력 22 | for d in range(T): 23 | print(Answer[d]) 24 | -------------------------------------------------------------------------------- /codes/cpp/chap06/code_6-02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | // 입력 6 | int N, A[200009]; long long Answer = 0; 7 | cin >> N; 8 | for (int i = 1; i <= N; i++) cin >> A[i]; 9 | 10 | // 완전 탐색(선택하는 막대의 번호를 오름차순으로 i, j, k라 한다) 11 | for (int i = 1; i <= N; i++) { 12 | for (int j = i + 1; j <= N; j++) { 13 | for (int k = j + 1; k <= N; k++) { 14 | if (A[i] == A[j] && A[j] == A[k]) Answer += 1; 15 | } 16 | } 17 | } 18 | cout << Answer << endl; 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /codes/python/chap03/answer_A13.py: -------------------------------------------------------------------------------- 1 | # 입력(A는 0번부터 시작한다는 점에 유의) 2 | N, K = map(int, input().split()) 3 | A = list(map(int, input().split())) 4 | 5 | # 배열 준비(R은 0번부터 시작한다는 점에 유의) 6 | R = [ None ] * N 7 | 8 | # 자벌레 알고리즘 9 | for i in range(0, N-1): 10 | # 시작 지점을 결정한다 11 | if i == 0: 12 | R[i] = 0 13 | else: 14 | R[i] = R[i - 1] 15 | 16 | # 한계까지 더해간다 17 | while R[i] < N-1 and A[R[i]+1]-A[i] <= K: 18 | R[i] += 1 19 | 20 | # 출력 21 | Answer = 0 22 | for i in range(0, N-1): 23 | Answer += (R[i] - i) 24 | print(Answer) 25 | -------------------------------------------------------------------------------- /codes/python/chap04/answer_A19.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, W = map(int, input().split()) 3 | w = [ None ] * (N + 1) 4 | v = [ None ] * (N + 1) 5 | for i in range(1, N+1): 6 | w[i], v[i] = map(int, input().split()) 7 | 8 | # 동적 계획 알고리즘 9 | dp = [ [ -10 ** 15 ] * (W + 1) for i in range(N + 1) ] 10 | dp[0][0] = 0 11 | for i in range(1, N+1): 12 | for j in range(0,W+1): 13 | if j < w[i]: 14 | dp[i][j] = dp[i-1][j] 15 | if j >= w[i]: 16 | dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]) 17 | 18 | # 출력 19 | print(max(dp[N])) 20 | -------------------------------------------------------------------------------- /codes/python/chap04/answer_A24_withoutDP.py: -------------------------------------------------------------------------------- 1 | ########################### 2 | # 배열 dp를 사용하지 않는 구현 3 | ########################### 4 | 5 | import bisect 6 | 7 | # 입력(A는 0번부터 시작한다는 점에 주의!) 8 | N = int(input()) 9 | A = list(map(int, input().split())) 10 | 11 | # 동적 계획 알고리즘의 준비 12 | LEN = 0 13 | L = [] 14 | 15 | # 동적 계획 알고리즘(배열 dp를 이용한 구현) 16 | for i in range(N): 17 | pos = bisect.bisect_left(L, A[i]) 18 | if pos >= LEN: 19 | L.append(A[i]) 20 | LEN += 1 21 | else: 22 | L[pos] = A[i] 23 | 24 | # 답을 출력 25 | print(LEN) 26 | -------------------------------------------------------------------------------- /codes/python/chap05/answer_A28.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | T = [ None ] * N 4 | A = [ None ] * N 5 | for i in range(N): 6 | T[i], A[i] = input().split() 7 | A[i] = int(A[i]) 8 | 9 | # 출력(Answer는 현재 칠판의 수) 10 | Answer = 0 11 | for i in range(N): 12 | if T[i] == '+': 13 | Answer += A[i] 14 | if T[i] == '-': 15 | Answer -= A[i] 16 | if T[i] == '*': 17 | Answer *= A[i] 18 | 19 | # 뺄셈의 답이 0 미만이 된 경우 20 | if Answer < 0: 21 | Answer += 10000 22 | 23 | # 여기에서 나머지를 구한다! 24 | Answer %= 10000 25 | print(Answer) 26 | -------------------------------------------------------------------------------- /codes/python/chap05/answer_A35.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | A = list(map(int, input().split())) 4 | 5 | # 배열 dp 정의 6 | dp = [ [ None ] * (N+1) for i in range(N+1) ] 7 | 8 | # 동적 계획 알고리즘 [N 단계] 9 | for j in range(1, N+1): 10 | dp[N][j] = A[j-1] 11 | 12 | # 동적 계획 알고리즘 [1 ~ N-1 단계] 13 | for i in reversed(range(1, N)): 14 | for j in range(1, i+1): 15 | if i % 2 == 1: 16 | dp[i][j] = max(dp[i+1][j], dp[i+1][j+1]) 17 | if i % 2 == 0: 18 | dp[i][j] = min(dp[i+1][j], dp[i+1][j+1]) 19 | 20 | # 출력 21 | print(dp[1][1]) 22 | -------------------------------------------------------------------------------- /codes/cpp/chap02/answer_A06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, A[100009], S[100009]; 5 | int Q, L[100009], R[100009]; 6 | 7 | int main() { 8 | // 입력 9 | cin >> N >> Q; 10 | for (int i = 1; i <= N; i++) cin >> A[i]; 11 | for (int j = 1; j <= Q; j++) cin >> L[j] >> R[j]; 12 | 13 | // 누적 합 계산 14 | S[0] = 0; 15 | for (int i = 1; i <= N; i++) S[i] = S[i - 1] + A[i]; 16 | 17 | // 질문에 답한다 18 | for (int j = 1; j <= Q; j++) { 19 | cout << S[R[j]] - S[L[j] - 1] << endl; 20 | } 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /codes/cpp/chap04/answer_A16.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, A[100009], B[100009]; 6 | int dp[100009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N; 11 | for (int i = 2; i <= N; i++) cin >> A[i]; 12 | for (int i = 3; i <= N; i++) cin >> B[i]; 13 | 14 | // 동적 계획 알고리즘 15 | dp[1] = 0; 16 | dp[2] = A[2]; 17 | for (int i = 3; i <= N; i++) { 18 | dp[i] = min(dp[i - 1] + A[i], dp[i - 2] + B[i]); 19 | } 20 | 21 | // 출력 22 | cout << dp[N] << endl; 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /codes/java/chap01/answer_A05.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int K = sc.nextInt(); 10 | 11 | // 완전 탐색 12 | int Answer = 0; 13 | for (int x = 1; x <= N; x++) { 14 | for (int y = 1; y <= N; y++) { 15 | int z = K - x - y; // 흰 카드에 적혀야 하는 정수 16 | if (z >= 1 && z <= N) Answer += 1; 17 | } 18 | } 19 | 20 | // 출력 21 | System.out.println(Answer); 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /editorial/chap06/python/answer_B44.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | A = [ None ] * N 4 | for i in range(N): 5 | A[i] = list(map(int, input().split())) 6 | 7 | # 배열 T 초기화 8 | # 배열 A가 0으로 시작하므로 배열 T도 0으로 시작한다 9 | T = [ None ] * N 10 | for i in range(N): 11 | T[i] = i 12 | 13 | # 쿼리 처리 14 | Q = int(input()) 15 | for i in range(Q): 16 | Query = list(map(int, input().split())) 17 | if Query[0] == 1: 18 | T[Query[1]-1],T[Query[2]-1] = T[Query[2]-1],T[Query[1]-1] 19 | if Query[0] == 2: 20 | print(A[T[Query[1]-1]][Query[2]-1]) 21 | -------------------------------------------------------------------------------- /codes/cpp/chap07/code_7-08.cpp: -------------------------------------------------------------------------------- 1 | // X[t]=x, Y[t]=y, H[t]=h로 변경하는 함수 2 | void Change(int t, int x, int y, int h) { 3 | // X[t], Y[t], H[t]의 변경 4 | X[t] = x; 5 | Y[t] = y; 6 | H[t] = h; 7 | 8 | // 배열 B 리셋(0으로 되돌린다) 9 | for (int i = 0; i < N; i++) { 10 | for (int j = 0; j < N; j++) B[i][j] = 0; 11 | } 12 | 13 | // 배열 B 업데이트 14 | for (int q = 1; q <= Q; q++) { 15 | for (int i = 0; i < N; i++) { 16 | for (int j = 0; j < N; j++) { 17 | B[j][i] += max(0, H[q] - abs(X[q] - i) - abs(Y[q] - j)); 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /codes/cpp/chap07/code_7-09.cpp: -------------------------------------------------------------------------------- 1 | // X[t]=x, Y[t]=y, H[t]=h로 변경하는 함수 2 | void Change(int t, int x, int y, int h) { 3 | // X[t], Y[t], H[t]의 변경 4 | X[t] = x; 5 | Y[t] = y; 6 | H[t] = h; 7 | 8 | // 배열 B 리셋(0으로 되돌린다) 9 | for (int i = 0; i < N; i++) { 10 | for (int j = 0; j < N; j++) B[i][j] = 0; 11 | } 12 | 13 | // 배열 B 업데이트 14 | for (int q = 1; q <= Q; q++) { 15 | for (int i = 0; i < N; i++) { 16 | for (int j = 0; j < N; j++) { 17 | B[j][i] += max(0, H[q] - abs(X[q] - i) - abs(Y[q] - j)); 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /codes/cpp/chap08/code_8-01.cpp: -------------------------------------------------------------------------------- 1 | // 연상 배열 정의 | map<첨자_타입, 타입>의 형태 2 | // 연상 배열의 접근 | 일반적인 배열과 거의 같음 3 | // ---------------------------------------------------------------- 4 | 5 | // 첨자가 string 타입, 기록하는 값이 int 타입인 연상 배열을 정의 6 | map Map; 7 | 8 | // 연상 배열 접근 9 | Map["tanaka"] = 49; 10 | Map["suzuki"] = 50; 11 | cout << Map["tanaka"] << endl; // 49가 출력된다 12 | cout << Map["suzuki"] << endl; // 50이 출력된다 13 | 14 | Map["suzuki"] = 53; 15 | cout << Map["suzuki"] << endl; // 53이 출력된다 16 | cout << Map["sato"] << endl; // 0이 출력된다 17 | -------------------------------------------------------------------------------- /codes/python/chap04/answer_A25.py: -------------------------------------------------------------------------------- 1 | # 입력 (배열 c가 0번부터 시작한다는 점에 유의) 2 | H, W = map(int, input().split()) 3 | c = [ None ] * H 4 | for i in range(H): 5 | c[i] = input() 6 | 7 | # 동적 계획 알고리즘 8 | dp = [ [ 0 ] * (W + 1) for i in range(H + 1) ] 9 | for i in range(H): 10 | for j in range(W): 11 | if i==0 and j==0: 12 | dp[i][j] = 1 13 | else: 14 | dp[i][j] = 0 15 | if i>=1 and c[i-1][j]=='.': 16 | dp[i][j] += dp[i-1][j] 17 | if j>=1 and c[i][j-1]=='.': 18 | dp[i][j] += dp[i][j-1] 19 | 20 | # 출력 21 | print(dp[H-1][W-1]) 22 | -------------------------------------------------------------------------------- /codes/python/chap09/answer_A65.py: -------------------------------------------------------------------------------- 1 | # 입력(A[2], ... , A[N]이 입력되는 값이 되도록 한다. , A[N]이 입력되는 값으로 설정) 2 | N = int(input()) 3 | A = [ 0 ] * 2 + list(map(int, input().split())) 4 | 5 | # 인접 리스트 생성 6 | G = [ list() for i in range(N + 1) ] 7 | for i in range(2, N + 1): 8 | G[A[i]].append(i) # 상사 → 부하직원 방향으로 방향 에지 추가 9 | 10 | # 동적 계획 알고리즘(dp[x]는 직원 x의 부하직원 수) 11 | dp = [ 0 ] * (N + 1) 12 | for i in range(N, 0, -1): 13 | for j in G[i]: 14 | dp[i] += (dp[j] + 1) 15 | 16 | # 답 (dp[1], dp[2], ... , dp[N])를 공백으로 구분하여 출력 17 | print(*dp[1:]) -------------------------------------------------------------------------------- /editorial/chap04/cpp/answer_B16.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int N, H[100009]; 7 | int dp[100009]; 8 | 9 | int main() { 10 | // 입력 11 | cin >> N; 12 | for (int i = 1; i <= N; i++) cin >> H[i]; 13 | 14 | // 동적 계획 알고리즘 15 | dp[1] = 0; 16 | dp[2] = abs(H[1] - H[2]); 17 | for (int i = 3; i <= N; i++) { 18 | dp[i] = min(dp[i - 1] + abs(H[i - 1] - H[i]), dp[i - 2] + abs(H[i - 2] - H[i])); 19 | } 20 | 21 | // 출력 22 | cout << dp[N] << endl; 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /codes/cpp/chap06/answer_A37.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | long long N, M, B; 5 | long long A[200009], C[200009]; 6 | 7 | int main() { 8 | // 입력 9 | cin >> N >> M >> B; 10 | for (int i = 1; i <= N; i++) cin >> A[i]; 11 | for (int j = 1; j <= M; j++) cin >> C[j]; 12 | 13 | // 답 계산 14 | long long Answer = 0; 15 | for (int i = 1; i <= N; i++) Answer += A[i] * M; 16 | Answer += B * N * M; 17 | for (int j = 1; j <= M; j++) Answer += C[j] * N; 18 | 19 | // 출력 20 | cout << Answer << endl; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /codes/python/chap03/answer_A11.py: -------------------------------------------------------------------------------- 1 | # 정수 x가 몇 번째에 위치하는지 반환한다 2 | def search(x, A): 3 | L = 0 4 | R = N-1 5 | while L <= R: 6 | M = (L + R) // 2 7 | if x < A[M]: 8 | R = M - 1 9 | if x == A[M]: 10 | return M 11 | if x > A[M]: 12 | L = M + 1 13 | return -1 # 정수 x가 존재하지 않는다(주: 이 문제의 조건에서 -1이 반환되는 일은 없다) 14 | 15 | 16 | # 입력(배열 X가 0번부터 시작한다는 점에 유의) 17 | N, X = map(int, input().split()) 18 | A = list(map(int, input().split())) 19 | 20 | # 바이너리 서치를 수행한다(배열이 0번부터 시작하므로 답에 1을 더한 것이다.) 21 | Answer = search(X, A) 22 | print(Answer + 1) 23 | -------------------------------------------------------------------------------- /editorial/chap03/cpp/answer_B11.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, A[100009]; 6 | int Q, X[100009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N; 11 | for (int i = 1; i <= N; i++) cin >> A[i]; 12 | cin >> Q; 13 | for (int i = 1; i <= Q; i++) cin >> X[i]; 14 | 15 | // 배열 X 정렬 16 | sort(A + 1, A + N + 1); 17 | 18 | // 질문에 답한다 19 | for (int i = 1; i <= Q; i++) { 20 | int pos1 = lower_bound(A + 1, A + N + 1, X[i]) - A; 21 | cout << pos1 - 1 << endl; 22 | } 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /codes/cpp/chap10/answer_A71.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, A[69], B[69]; 6 | int Answer = 0; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N; 11 | for (int i = 1; i <= N; i++) cin >> A[i]; 12 | for (int i = 1; i <= N; i++) cin >> B[i]; 13 | 14 | // 배열 정렬(reverse 함수는 배열을 역순으로 하는 함수) 15 | sort(A + 1, A + N + 1); 16 | sort(B + 1, B + N + 1); reverse(B + 1, B + N + 1); 17 | 18 | // 답을 구한다 19 | for (int i = 1; i <= N; i++) Answer += A[i] * B[i]; 20 | cout << Answer << endl; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /codes/python/chap04/answer_A20.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | S = input() 3 | T = input() 4 | N = len(S) 5 | M = len(T) 6 | 7 | # 동적 계획 알고리즘 8 | dp = [ [ None ] * (M + 1) for i in range(N + 1) ] 9 | dp[0][0] = 0 10 | for i in range(0, N+1): 11 | for j in range(0,M+1): 12 | if i>=1 and j>=1 and S[i-1]==T[j-1]: 13 | dp[i][j] = max(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]+1) 14 | elif i>=1 and j>=1: 15 | dp[i][j] = max(dp[i-1][j], dp[i][j-1]) 16 | elif i>=1: 17 | dp[i][j] = dp[i-1][j] 18 | elif j>=1: 19 | dp[i][j] = dp[i][j-1] 20 | 21 | # 출력 22 | print(dp[N][M]) 23 | -------------------------------------------------------------------------------- /codes/python/chap04/answer_A24.py: -------------------------------------------------------------------------------- 1 | import bisect 2 | 3 | # 입력(A는 0번부터 시작한다는 점에 주의!) 4 | N = int(input()) 5 | A = list(map(int, input().split())) 6 | 7 | # 동적 계획 알고리즘의 준비 8 | LEN = 0 # LEN은 L의 길이 (예: L[3]까지 기록된 경우 LEN=4) 9 | L = [] # 0부터 시작하는 것에 주의 10 | dp = [ None ] * N # 0부터 시작하는 것에 주의 11 | 12 | # 동적 계획 알고리즘(배열 dp를 이용한 구현) 13 | for i in range(N): 14 | pos = bisect.bisect_left(L, A[i]) 15 | dp[i] = pos 16 | 17 | # 배열 L을 업데이트 18 | if dp[i] >= LEN: 19 | L.append(A[i]) 20 | LEN += 1 21 | else: 22 | L[dp[i]] = A[i] 23 | 24 | # 답을 출력 25 | print(LEN) 26 | -------------------------------------------------------------------------------- /codes/cpp/chap06/answer_A40.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | // 입력 6 | int N, A[200009]; long long cnt[109], Answer = 0; 7 | cin >> N; 8 | for (int i = 1; i <= N; i++) cin >> A[i]; 9 | 10 | // 개수를 센다 11 | for (int i = 1; i <= 100; i++) cnt[i] = 0; 12 | for (int i = 1; i <= N; i++) cnt[A[i]] += 1; 13 | 14 | // 답을 구한다 15 | // nC3 = n * (n-1) * (n-2) / 6 을 사용한다 16 | for (int i = 1; i <= 100; i++) { 17 | Answer += cnt[i] * (cnt[i] - 1) * (cnt[i] - 2) / 6; 18 | } 19 | cout << Answer << endl; 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /codes/cpp/chap06/answer_A41.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | // 입력 6 | int N; char S[200009]; 7 | cin >> N; 8 | for (int i = 1; i <= N; i++) cin >> S[i]; 9 | 10 | // 답을 구한다 11 | bool Answer = false; 12 | for (int i = 1; i <= N - 2; i++) { 13 | if (S[i] == 'R' && S[i + 1] == 'R' && S[i + 2] == 'R') Answer = true; 14 | if (S[i] == 'B' && S[i + 1] == 'B' && S[i + 2] == 'B') Answer = true; 15 | } 16 | 17 | // 출력 18 | if (Answer == true) cout << "Yes" << endl; 19 | else cout << "No" << endl; 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /codes/java/chap05/answer_A33.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int[] A = new int[N + 1]; 10 | for (int i = 1; i <= N; i++) A[i] = sc.nextInt(); 11 | 12 | // 전부 XOR한 값(Nim sum)을 구한다 13 | int XOR_Sum = A[1]; 14 | for (int i = 2; i <= N; i++) XOR_Sum = (XOR_Sum ^ A[i]); 15 | 16 | // 출력 17 | if (XOR_Sum != 0) System.out.println("First"); 18 | if (XOR_Sum == 0) System.out.println("Second"); 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /editorial/chap01/cpp/answer_B03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | // 입력 6 | int N, A[109]; 7 | cin >> N; 8 | for (int i = 1; i <= N; i++) cin >> A[i]; 9 | 10 | // 답을 구한다 11 | bool Answer = false; 12 | for (int i = 1; i <= N; i++) { 13 | for (int j = i + 1; j <= N; j++) { 14 | for (int k = j + 1; k <= N; k++) { 15 | if (A[i] + A[j] + A[k] == 1000) Answer = true; 16 | } 17 | } 18 | } 19 | 20 | // 출력 21 | if (Answer == true) cout << "Yes" << endl; 22 | else cout << "No" << endl; 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /editorial/final/cpp/answer_C09.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | long long N, A[500009]; 6 | long long dp1[500009], dp2[500009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N; 11 | for (int i = 1; i <= N; i++) cin >> A[i]; 12 | 13 | // 배열 초기화 14 | dp1[0] = 0; 15 | dp2[0] = 0; 16 | 17 | // 동적 계획 알고리즘 18 | for (int i = 1; i <= N; i++) { 19 | dp1[i] = dp2[i - 1] + A[i]; 20 | dp2[i] = max(dp1[i - 1], dp2[i - 1]); 21 | } 22 | 23 | // 답을 출력 24 | cout << max(dp1[N], dp2[N]) << endl; 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /editorial/chap05/answer_B33.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int H, W; 5 | int N, A[200009], B[200009]; 6 | 7 | int main() { 8 | // 입력 9 | cin >> N >> H >> W; 10 | for (int i = 1; i <= N; i++) cin >> A[i] >> B[i]; 11 | 12 | // 전부 XOR한 값(Nim sum)을 구한다 13 | int XOR_Sum = 0; 14 | for (int i = 1; i <= N; i++) XOR_Sum = (XOR_Sum ^ (A[i] - 1)); 15 | for (int i = 1; i <= N; i++) XOR_Sum = (XOR_Sum ^ (B[i] - 1)); 16 | 17 | // 출력 18 | if (XOR_Sum != 0) cout << "First" << endl; 19 | if (XOR_Sum == 0) cout << "Second" << endl; 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /editorial/chap08/python/answer_B53.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | 3 | 4 | G = [list() for _ in range(2005)] # G[i]는 i 일째부터 시작하는 직업의 급여 목록이다 5 | 6 | # 입력 7 | N, D = map(int, input().split()) 8 | for _ in range(N): 9 | X, Y = map(int, input().split()) 10 | G[X].append(Y) 11 | 12 | # 답을 구한다 13 | Q = [] 14 | Answer = 0 15 | for i in range(1, D + 1): 16 | # i 일차부터 시작하는 작업을 대기열에 추가한다 17 | # heap 은 최소값을 가져 오기 때문에 -1 배로 한다 18 | for y in G[i]: heapq.heappush(Q, -y) 19 | 20 | # 할 일을 선택하고 해당 작업을 대기열에서 삭제한다 21 | if Q: 22 | Answer -= heapq.heappop(Q) 23 | 24 | # 출력 25 | print(Answer) 26 | -------------------------------------------------------------------------------- /editorial/chap03/cpp/answer_B12.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // 함수 f 5 | double f(double x) { 6 | return x * x * x + x; 7 | } 8 | 9 | int main() { 10 | // 입력 11 | int N; 12 | cin >> N; 13 | 14 | // 바이너리 서치 15 | double Left = 0, Right = 100, Mid; 16 | for (int i = 0; i < 20; i++) { 17 | Mid = (Left + Right) / 2.0; 18 | double val = f(Mid); 19 | 20 | // 탐색 범위 좁히기 21 | if (val > 1.0 * N) Right = Mid; // 왼쪽 절반으로 쪼개진다 22 | else Left = Mid; // 오른쪽 절반으로 쪼개진다 23 | } 24 | 25 | // 출력 26 | printf("%.12lf\n", Mid); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /editorial/chap05/cpp/answer_B33.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int H, W; 5 | int N, A[200009], B[200009]; 6 | 7 | int main() { 8 | // 입력 9 | cin >> N >> H >> W; 10 | for (int i = 1; i <= N; i++) cin >> A[i] >> B[i]; 11 | 12 | // 전부 XOR한 값(Nim sum)을 구한다 13 | int XOR_Sum = 0; 14 | for (int i = 1; i <= N; i++) XOR_Sum = (XOR_Sum ^ (A[i] - 1)); 15 | for (int i = 1; i <= N; i++) XOR_Sum = (XOR_Sum ^ (B[i] - 1)); 16 | 17 | // 출력 18 | if (XOR_Sum != 0) cout << "First" << endl; 19 | if (XOR_Sum == 0) cout << "Second" << endl; 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /codes/cpp/chap02/answer_A07.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, L[100009], R[100009]; 5 | int D, B[100009]; 6 | int Answer[100009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> D >> N; 11 | for (int i = 1; i <= N; i++) cin >> L[i] >> R[i]; 12 | 13 | // 전일 비에 더한다 14 | for (int i = 1; i <= N; i++) { 15 | B[L[i]] += 1; 16 | B[R[i] + 1] -= 1; 17 | } 18 | 19 | // 누적 합을 구한다 → 출력 20 | Answer[0] = 0; 21 | for (int d = 1; d <= D; d++) Answer[d] = Answer[d - 1] + B[d]; 22 | for (int d = 1; d <= D; d++) cout << Answer[d] << endl; 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /codes/cpp/chap08/code_8-02.cpp: -------------------------------------------------------------------------------- 1 | set S; 2 | 3 | // 조작을 수행한다 4 | S.insert(1); // S = {1} 5 | S.insert(2); // S = {1, 2} 6 | S.insert(4); // S = {1, 2, 4} 7 | S.insert(2); // S = {1, 2, 4} ← 여기에서 {1, 2, 2, 4}가 되지 않는 것에 주의! 8 | cout << S.size() << endl; // 3이 출력된다 9 | 10 | S.erase(2); // S = {1, 4} 11 | S.insert(9); // S = {1, 4, 9} 12 | S.insert(9); // S = {1, 4, 9} ← 여기에서 {1, 4, 9, 9}가 되지 않는 것에 주의! 13 | cout << S.size() << endl; // 3이 출력된다 14 | 15 | if (S.count(2) == 1) cout << "2 is included" << endl; // 출력되지 않는다 16 | if (S.count(9) == 1) cout << "9 is included" << endl; // 출력된다 17 | -------------------------------------------------------------------------------- /codes/python/chap10/answer_A74.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | P = [ list(map(int, input().split())) for i in range(N) ] 4 | 5 | # "이전 수를 구하는 문제"를 2가지로 나눕니다. 6 | X = [ None ] * N 7 | Y = [ None ] * N 8 | for i in range(N): 9 | for j in range(N): 10 | if P[i][j] != 0: 11 | X[i] = P[i][j] 12 | Y[j] = P[i][j] 13 | 14 | # 역수를 구하는 관련 수 15 | def inversion(A): 16 | answer = 0 17 | for i in range(len(A)): 18 | for j in range(i + 1, len(A)): 19 | if A[i] > A[j]: 20 | answer += 1 21 | return answer 22 | 23 | # 답을 출력 24 | print(inversion(X) + inversion(Y)) -------------------------------------------------------------------------------- /editorial/chap04/python/answer_B21.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | S = input() 4 | 5 | # 동적 계획 알고리즘(초기 상태) 6 | dp = [ [ None ] * N for i in range(N) ] 7 | for i in range(N): 8 | dp[i][i] = 1 9 | for i in range(N-1): 10 | if S[i] == S[i+1]: 11 | dp[i][i+1] = 2 12 | else: 13 | dp[i][i+1] = 1 14 | 15 | # 동적 계획 알고리즘(상태 전환) 16 | for LEN in range(2,N): 17 | for l in range(N-LEN): 18 | r = l + LEN 19 | if S[l] == S[r]: 20 | dp[l][r] = max(dp[l][r-1], dp[l+1][r], dp[l+1][r-1]+2) 21 | else: 22 | dp[l][r] = max(dp[l][r-1], dp[l+1][r]) 23 | 24 | # 출력 25 | print(dp[0][N-1]) 26 | -------------------------------------------------------------------------------- /codes/cpp/chap08/answer_A51.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int Q; 7 | int QueryType[100009]; string x[100009]; 8 | stack S; 9 | 10 | int main() { 11 | // 입력 12 | cin >> Q; 13 | for (int i = 1; i <= Q; i++) { 14 | cin >> QueryType[i]; 15 | if (QueryType[i] == 1) cin >> x[i]; 16 | } 17 | 18 | // 쿼리 처리 19 | for (int i = 1; i <= Q; i++) { 20 | if (QueryType[i] == 1) S.push(x[i]); 21 | if (QueryType[i] == 2) cout << S.top() << endl; 22 | if (QueryType[i] == 3) S.pop(); 23 | } 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /codes/cpp/chap08/answer_A52.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int Q; 7 | int QueryType[100009]; string x[100009]; 8 | queue T; 9 | 10 | int main() { 11 | // 입력 12 | cin >> Q; 13 | for (int i = 1; i <= Q; i++) { 14 | cin >> QueryType[i]; 15 | if (QueryType[i] == 1) cin >> x[i]; 16 | } 17 | 18 | // 쿼리 처리 19 | for (int i = 1; i <= Q; i++) { 20 | if (QueryType[i] == 1) T.push(x[i]); 21 | if (QueryType[i] == 2) cout << T.front() << endl; 22 | if (QueryType[i] == 3) T.pop(); 23 | } 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /editorial/chap05/answer_B26.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N; 5 | bool Deleted[1000009]; // 정수 x가 지워진 경우에 한해 Deleted[x]=true 6 | 7 | int main() { 8 | // 입력 9 | cin >> N; 10 | 11 | // 엘라토스테네스의 체 (i는 √N 이하의 최대 정수까지 반복) 12 | for (int i = 2; i <= N; i++) Deleted[i] = false; 13 | for (int i = 2; i * i <= N; i++) { 14 | if (Deleted[i] == true) continue; 15 | for (int j = i * 2; j <= N; j += i) Deleted[j] = true; 16 | } 17 | 18 | // 답을 출력 19 | for (int i = 2; i <= N; i++) { 20 | if (Deleted[i] == false) cout << i << endl; 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /codes/cpp/chap05/answer_A26.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // x가 소수일 때 true, 소수가 아닐 때 false를 반환한다 5 | bool isPrime(int x) { 6 | for (int i = 2; i * i <= x; i++) { 7 | if (x % i == 0) return false; 8 | } 9 | return true; 10 | } 11 | 12 | int main() { 13 | // 입력 14 | int Q, X[10009]; 15 | cin >> Q; 16 | for (int i = 1; i <= Q; i++) cin >> X[i]; 17 | 18 | // 출력 19 | for (int i = 1; i <= Q; i++) { 20 | bool Answer = isPrime(X[i]); 21 | if (Answer == true) cout << "Yes" << endl; 22 | if (Answer == false) cout << "No" << endl; 23 | } 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /codes/cpp/chap05/answer_A32.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // 배열 dp에 대해: dp[x]=true일 때 승리 상태, dp[x]=false일 때 패배 상태 5 | int N, A, B; 6 | bool dp[100009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N >> A >> B; 11 | 12 | // 승자를 계산한다 13 | for (int i = 0; i <= N; i++) { 14 | if (i >= A && dp[i - A] == false) dp[i] = true; // 승리 상태 15 | else if (i >= B && dp[i - B] == false) dp[i] = true; // 승리 상태 16 | else dp[i] = false; // 패배 상태 17 | } 18 | 19 | // 출력 20 | if (dp[N] == true) cout << "First" << endl; 21 | else cout << "Second" << endl; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /editorial/chap05/cpp/answer_B26.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N; 5 | bool Deleted[1000009]; // 정수 x가 지워진 경우에 한해 Deleted[x]=true 6 | 7 | int main() { 8 | // 입력 9 | cin >> N; 10 | 11 | // 엘라토스테네스의 체 (i는 √N 이하의 최대 정수까지 반복) 12 | for (int i = 2; i <= N; i++) Deleted[i] = false; 13 | for (int i = 2; i * i <= N; i++) { 14 | if (Deleted[i] == true) continue; 15 | for (int j = i * 2; j <= N; j += i) Deleted[j] = true; 16 | } 17 | 18 | // 답을 출력 19 | for (int i = 2; i <= N; i++) { 20 | if (Deleted[i] == false) cout << i << endl; 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /editorial/chap04/python/answer_B20.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | S = input() 3 | T = input() 4 | 5 | # 배열 준비 6 | dp = [ [ None ] * (len(T) + 1) for i in range(len(S) + 1) ] 7 | 8 | # 동적 계획 알고리즘 9 | dp[0][0] = 0 10 | for i in range(len(S)+1): 11 | for j in range(len(T)+1): 12 | if i>=1 and j>=1 and S[i-1]==T[j-1]: 13 | dp[i][j] = min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i-1][j-1]) 14 | elif i>=1 and j>=1: 15 | dp[i][j] = min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i-1][j-1]+1) 16 | elif i>=1: 17 | dp[i][j] = dp[i-1][j]+1 18 | elif j>=1: 19 | dp[i][j] = dp[i][j-1]+1 20 | 21 | # 출력 22 | print(dp[len(S)][len(T)]) 23 | -------------------------------------------------------------------------------- /editorial/chap05/answer_B34.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | long long N, X, Y, A[100009]; 5 | 6 | int main() { 7 | // 입력 8 | cin >> N >> X >> Y; 9 | for (int i = 1; i <= N; i++) cin >> A[i]; 10 | 11 | // Grundy 수 계산 12 | int XOR_Sum = 0; 13 | for (int i = 1; i <= N; i++) { 14 | if (A[i] % 5 == 0 || A[i] % 5 == 1) XOR_Sum ^= 0; 15 | if (A[i] % 5 == 2 || A[i] % 5 == 3) XOR_Sum ^= 1; 16 | if (A[i] % 5 == 4) XOR_Sum ^= 2; 17 | } 18 | 19 | // 출력 20 | if (XOR_Sum != 0) cout << "First" << endl; 21 | if (XOR_Sum == 0) cout << "Second" << endl; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /codes/cpp/chap01/answer_A03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, K; 5 | int P[109], Q[109]; 6 | bool Answer = false; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N >> K; 11 | for (int i = 1; i <= N; i++) cin >> P[i]; 12 | for (int i = 1; i <= N; i++) cin >> Q[i]; 13 | 14 | // 완전 탐색(Answer는 '합계가 K가 되는 선택 방법을 발견했는가'를 나타냄) 15 | for (int x = 1; x <= N; x++) { 16 | for (int y = 1; y <= N; y++) { 17 | if (P[x] + Q[y] == K) Answer = true; 18 | } 19 | } 20 | 21 | // 출력 22 | if (Answer == true) cout << "Yes" << endl; 23 | else cout << "No" << endl; 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /codes/cpp/chap04/answer_A24.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, A[100009], dp[100009]; 6 | int LEN = 0, L[100009]; // LEN은 L의 길이(예: L[4]까지 쓰여 있는 경우 LEN=4) 7 | 8 | int main() { 9 | // 입력 10 | cin >> N; 11 | for (int i = 1; i <= N; i++) cin >> A[i]; 12 | 13 | // 동적 계획 알고리즘 14 | for (int i = 1; i <= N; i++) { 15 | int pos = lower_bound(L + 1, L + LEN + 1, A[i]) - L; 16 | dp[i] = pos; 17 | 18 | // 배열 L을 업데이트 19 | L[dp[i]] = A[i]; 20 | if (dp[i] > LEN) LEN += 1; 21 | } 22 | 23 | // 답을 출력 24 | cout << LEN << endl; 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /codes/cpp/chap08/answer_A55.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main() { 6 | // 입력 7 | int Q, QueryType[100009], x[100009]; 8 | cin >> Q; 9 | for (int i = 1; i <= Q; i++) cin >> QueryType[i] >> x[i]; 10 | 11 | // 쿼리 처리 12 | set S; 13 | for (int i = 1; i <= Q; i++) { 14 | if (QueryType[i] == 1) S.insert(x[i]); 15 | if (QueryType[i] == 2) S.erase(x[i]); 16 | if (QueryType[i] == 3) { 17 | auto itr = S.lower_bound(x[i]); 18 | if (itr == S.end()) cout << "-1" << endl; 19 | else cout << (*itr) << endl; 20 | } 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /editorial/chap04/python/answer_B19.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, W = map(int, input().split()) 3 | w = [ None ] * (N + 1) 4 | v = [ None ] * (N + 1) 5 | for i in range(1, N+1): 6 | w[i], v[i] = map(int, input().split()) 7 | 8 | # 동적 계획 알고리즘 9 | dp = [ [ 10 ** 15 ] * 100001 for i in range(N + 1) ] 10 | dp[0][0] = 0 11 | for i in range(1, N+1): 12 | for j in range(100001): 13 | if j < v[i]: 14 | dp[i][j] = dp[i-1][j] 15 | if j >= v[i]: 16 | dp[i][j] = min(dp[i-1][j], dp[i-1][j-v[i]]+w[i]) 17 | 18 | # 출력 19 | Answer = 0 20 | for i in range(100001): 21 | if dp[N][i] <= W: 22 | Answer = i 23 | print(Answer) 24 | -------------------------------------------------------------------------------- /editorial/chap05/cpp/answer_B34.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | long long N, X, Y, A[100009]; 5 | 6 | int main() { 7 | // 입력 8 | cin >> N >> X >> Y; 9 | for (int i = 1; i <= N; i++) cin >> A[i]; 10 | 11 | // Grundy 수 계산 12 | int XOR_Sum = 0; 13 | for (int i = 1; i <= N; i++) { 14 | if (A[i] % 5 == 0 || A[i] % 5 == 1) XOR_Sum ^= 0; 15 | if (A[i] % 5 == 2 || A[i] % 5 == 3) XOR_Sum ^= 1; 16 | if (A[i] % 5 == 4) XOR_Sum ^= 2; 17 | } 18 | 19 | // 출력 20 | if (XOR_Sum != 0) cout << "First" << endl; 21 | if (XOR_Sum == 0) cout << "Second" << endl; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /codes/python/chap08/answer_A53.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | 3 | # 입력 4 | Q = int(input()) # 쿼리 개수 5 | queries = [ input().split() for i in range(Q) ] # 쿼리 정보(각 요소는 ["1", 값을 나타내는 문자열] or ["2"] or ["3"]이다.) 6 | 7 | # 쿼리 처리 8 | T = [] 9 | for q in queries: 10 | if q[0] == "1": 11 | heapq.heappush(T, int(q[1])) 12 | if q[0] == "2": 13 | print(T[0]) # T[0]은 '우선순위 대기열 중 가장 작은 요소'이다. 14 | if q[0] == "3": 15 | heapq.heappop(T) 16 | 17 | # 참고 1: Python의 heapq 모듈은 deque 모듈과 달리 함수를 사용하여 list를 조작하는 형식이다. 18 | # 참고 2: 우선순위가 있는 큐의 최소 요소는 T[0]으로 가져올 수 있지만, 예를 들어 작은 것부터 두 번째 요소는 T[1]로 가져올 수 있는 것은 아니라는 점에 유의한다. -------------------------------------------------------------------------------- /codes/python/chap09/answer_A61.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, M = map(int, input().split()) 3 | edges = [ list(map(int, input().split())) for i in range(M) ] 4 | 5 | # 인접 리스트 생성 6 | G = [ list() for i in range(N + 1) ] # G[i]는 버텍스 i에 인접한 버텍스의 목록 7 | for a, b in edges: 8 | G[a].append(b) # 정점 a 에 인접한 정점으로 b 를 추가한다. 9 | G[b].append(a) # 정점 b 에 인접한 정점으로 a 를 추가한다. 10 | 11 | # 출력 12 | for i in range(1, N + 1): 13 | output = '' 14 | output += str(i) 15 | output += ': {' 16 | output += ', '.join(map(str, G[i])) # 예를 들어 G[i] = { 2, 7, 5 }인 경우 "2, 7, 5"라는 문자열이 output 뒤에 연결된다. 17 | output += '}' 18 | print(output) -------------------------------------------------------------------------------- /editorial/final/cpp/answer_C04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | // 입력 8 | long long N; 9 | cin >> N; 10 | 11 | // 약수 열거 12 | vector Yakusuu; 13 | for (long long i = 1; i * i <= N; i++) { 14 | if (N % i == 0) { 15 | Yakusuu.push_back(i); 16 | if (i != N / i) Yakusuu.push_back(N / i); 17 | } 18 | } 19 | 20 | // 작은 순으로 정렬 21 | sort(Yakusuu.begin(), Yakusuu.end()); 22 | 23 | // 출력 24 | for (int i = 0; i < Yakusuu.size(); i++) { 25 | cout << Yakusuu[i] << endl; 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /codes/cpp/chap04/answer_A22.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, A[100009], B[100009], dp[100009]; 6 | 7 | int main() { 8 | // 입력 9 | cin >> N; 10 | for (int i = 1; i <= N - 1; i++) cin >> A[i]; 11 | for (int i = 1; i <= N - 1; i++) cin >> B[i]; 12 | 13 | // 배열 초기화 14 | dp[1] = 0; 15 | for (int i = 2; i <= N; i++) dp[i] = -1000000000; 16 | 17 | // 동적 계획 알고리즘 → 출력 18 | for (int i = 1; i <= N - 1; i++) { 19 | dp[A[i]] = max(dp[A[i]], dp[i] + 100); 20 | dp[B[i]] = max(dp[B[i]], dp[i] + 150); 21 | } 22 | cout << dp[N] << endl; 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /codes/cpp/chap05/answer_A29.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // a의 b제곱을 m으로 나눈 나머지를 반환하는 함수 5 | // 변수 p는 a^1 → a^2 → a^4 → a^8 → a^16 → ・・・으로 변화 6 | long long Power(long long a, long long b, long long m) { 7 | long long p = a, Answer = 1; 8 | for (int i = 0; i < 30; i++) { 9 | int wari = (1 << i); 10 | if ((b / wari) % 2 == 1) { 11 | Answer = (Answer * p) % m; // 'a의 2i 제곱'이 곱해졌을 때 12 | } 13 | p = (p * p) % m; 14 | } 15 | return Answer; 16 | } 17 | 18 | int main() { 19 | long long a, b; 20 | cin >> a >> b; 21 | cout << Power(a, b, 1000000007) << endl; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /codes/cpp/chap08/answer_A53.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int Q; 7 | int QueryType[100009], x[100009]; 8 | priority_queue, greater> T; 9 | 10 | int main() { 11 | // 입력 12 | cin >> Q; 13 | for (int i = 1; i <= Q; i++) { 14 | cin >> QueryType[i]; 15 | if (QueryType[i] == 1) cin >> x[i]; 16 | } 17 | 18 | // 쿼리 처리 19 | for (int i = 1; i <= Q; i++) { 20 | if (QueryType[i] == 1) T.push(x[i]); 21 | if (QueryType[i] == 2) cout << T.top() << endl; 22 | if (QueryType[i] == 3) T.pop(); 23 | } 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /codes/java/chap01/answer_A02.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int X = sc.nextInt(); 10 | int[] A = new int[N + 1]; 11 | for (int i = 1; i <= N; i++) A[i] = sc.nextInt(); 12 | 13 | // 완전 탐색(변수 Answer는 '기존에 x를 발견했는가'를 나타냄) 14 | boolean Answer = false; 15 | for (int i = 1; i <= N; i++) { 16 | if (A[i] == X) Answer = true; 17 | } 18 | 19 | // 출력 20 | if (Answer == true) System.out.println("Yes"); 21 | else System.out.println("No"); 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /codes/python/chap06/answer_A42.py: -------------------------------------------------------------------------------- 1 | # 정수의 쌍(a, b)가 결정되었을 때 참가 가능한 학생 수를 반환하는 함수 2 | def GetScore(a, b, A, B, K): 3 | cnt = 0 4 | for i in range(N): 5 | if a <= A[i] and A[i] <= a + K and b <= B[i] and B[i] <= b+K: 6 | cnt += 1 7 | return cnt 8 | 9 | # 입력 10 | N, K = map(int, input().split()) 11 | A = [ None ] * N 12 | B = [ None ] * N 13 | for i in range(N): 14 | A[i], B[i] = map(int, input().split()) 15 | 16 | # (a, b)쌍을 완전 탐색 17 | Answer = 0 18 | for a in range(1, 101): 19 | for b in range(1, 101): 20 | Score = GetScore(a, b, A, B, K) 21 | Answer = max(Answer, Score) 22 | 23 | # 출력 24 | print(Answer) 25 | -------------------------------------------------------------------------------- /codes/cpp/chap04/answer_A24_withoutDP.cpp: -------------------------------------------------------------------------------- 1 | // ########################### 2 | // # 배열 dp를 사용하지 않는 구현 3 | // ########################### 4 | 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | int N, A[100009]; 10 | int LEN = 0, L[100009]; 11 | 12 | int main() { 13 | // 입력 14 | cin >> N; 15 | for (int i = 1; i <= N; i++) cin >> A[i]; 16 | 17 | // 동적 계획 알고리즘 18 | for (int i = 1; i <= N; i++) { 19 | int pos = lower_bound(L + 1, L + LEN + 1, A[i]) - L; 20 | L[pos] = A[i]; 21 | if (pos > LEN) LEN += 1; 22 | } 23 | 24 | // 답을 출력 25 | cout << LEN << endl; 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /codes/cpp/chap08/answer_A54.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int Q; 7 | int QueryType[100009], y[100009]; 8 | string x[100009]; 9 | map Map; 10 | 11 | int main() { 12 | // 입력 13 | cin >> Q; 14 | for (int i = 1; i <= Q; i++) { 15 | cin >> QueryType[i]; 16 | if (QueryType[i] == 1) cin >> x[i] >> y[i]; 17 | if (QueryType[i] == 2) cin >> x[i]; 18 | } 19 | 20 | // 쿼리 처리 21 | for (int i = 1; i <= Q; i++) { 22 | if (QueryType[i] == 1) Map[x[i]] = y[i]; 23 | if (QueryType[i] == 2) cout << Map[x[i]] << endl; 24 | } 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /editorial/chap05/answer_B29.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // a의 b제곱을 m으로 나눈 나머지를 반환하는 함수 5 | // 변수 p는 a^1 → a^2 → a^4 → a^8 → a^16 → ・・・으로 변화 6 | long long Power(long long a, long long b, long long m) { 7 | long long p = a, Answer = 1; 8 | for (int i = 0; i < 60; i++) { 9 | long long wari = (1LL << i); 10 | if ((b / wari) % 2 == 1) { 11 | Answer = (Answer * p) % m; // 'a의 2i 제곱'이 곱해졌을 때 12 | } 13 | p = (p * p) % m; 14 | } 15 | return Answer; 16 | } 17 | 18 | int main() { 19 | long long a, b; 20 | cin >> a >> b; 21 | cout << Power(a, b, 1000000007) << endl; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /editorial/chap05/answer_B31.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | long long N; 6 | cin >> N; 7 | 8 | long long A1 = (N / 3); // 3으로 나누어떨어지는 수의 개수 9 | long long A2 = (N / 5); // 5로 나누어떨어지는 수의 개수 10 | long long A3 = (N / 7); // 5로 나누어떨어지는 수의 개수 11 | long long A4 = (N / 15); // 3, 5로 나누어떨어지는 수(= 15의 배수)의 개수 12 | long long A5 = (N / 21); // 3, 7로 나누어떨어지는 수(= 21의 배수)의 개수 13 | long long A6 = (N / 35); // 5, 7로 나누어떨어지는 수(= 35의 배수)의 개수 14 | long long A7 = (N / 105); // 3, 5, 7로 나누어떨어지는 수(= 105의 배수)의 개수 15 | cout << A1 + A2 + A3 - A4 - A5 - A6 + A7 << endl; 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /editorial/final/cpp/answer_C10.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // a의 b제곱을 m으로 나눈 나머지를 반환하는 함수 5 | long long Power(long long a, long long b, long long m) { 6 | long long p = a, Answer = 1; 7 | for (int i = 0; i < 60; i++) { 8 | long long wari = (1LL << i); 9 | if ((b / wari) % 2 == 1) { 10 | Answer = (Answer * p) % m; 11 | } 12 | p = (p * p) % m; 13 | } 14 | return Answer; 15 | } 16 | 17 | int main() { 18 | // 입력 19 | const long long mod = 1000000007; 20 | long long W; 21 | cin >> W; 22 | 23 | // 출력 24 | cout << 12LL * Power(7, W - 1, mod) % mod << endl; 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /codes/cpp/chap01/code_1-04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | // 입력 6 | int N, K, A[22]; 7 | cin >> N >> K; 8 | for (int i = 1; i <= N; i++) cin >> A[i]; 9 | 10 | // 완전 탐색(sum은 적혀있는 정수의 합계/ Answer는 현 시점에서의 답) 11 | bool Answer = false; 12 | for (int i = 0; i < (1 << N); i++) { 13 | int sum = 0; 14 | for (int j = 1; j <= N; j++) { 15 | int wari = (1 << (j - 1)); 16 | if ((i / wari) % 2 == 1) sum += A[j]; 17 | } 18 | if (sum == K) Answer = true; 19 | } 20 | 21 | // 출력 22 | if (Answer == true) cout << "Yes" << endl; 23 | else cout << "No" << endl; 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /codes/cpp/chap05/answer_A28.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | // 입력 6 | long long N, A[100009]; char T[100009]; 7 | cin >> N; 8 | for (int i = 1; i <= N; i++) cin >> T[i] >> A[i]; 9 | 10 | // 출력(Answer는 현재 칠판의 수) 11 | long long Answer = 0; 12 | for (int i = 1; i <= N; i++) { 13 | if (T[i] == '+') Answer += A[i]; 14 | if (T[i] == '-') Answer -= A[i]; 15 | if (T[i] == '*') Answer *= A[i]; 16 | 17 | // 뺄셈의 답이 0 미만이 된 경우 18 | if (Answer < 0) Answer += 10000; 19 | 20 | // 여기에서 나머지를 구한다! 21 | Answer %= 10000; 22 | cout << Answer << endl; 23 | } 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /editorial/chap05/cpp/answer_B29.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // a의 b제곱을 m으로 나눈 나머지를 반환하는 함수 5 | // 변수 p는 a^1 → a^2 → a^4 → a^8 → a^16 → ・・・으로 변화 6 | long long Power(long long a, long long b, long long m) { 7 | long long p = a, Answer = 1; 8 | for (int i = 0; i < 60; i++) { 9 | long long wari = (1LL << i); 10 | if ((b / wari) % 2 == 1) { 11 | Answer = (Answer * p) % m; // 'a의 2i 제곱'이 곱해졌을 때 12 | } 13 | p = (p * p) % m; 14 | } 15 | return Answer; 16 | } 17 | 18 | int main() { 19 | long long a, b; 20 | cin >> a >> b; 21 | cout << Power(a, b, 1000000007) << endl; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /editorial/chap05/cpp/answer_B31.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | long long N; 6 | cin >> N; 7 | 8 | long long A1 = (N / 3); // 3으로 나누어떨어지는 수의 개수 9 | long long A2 = (N / 5); // 5로 나누어떨어지는 수의 개수 10 | long long A3 = (N / 7); // 5로 나누어떨어지는 수의 개수 11 | long long A4 = (N / 15); // 3, 5로 나누어떨어지는 수(= 15의 배수)의 개수 12 | long long A5 = (N / 21); // 3, 7로 나누어떨어지는 수(= 21의 배수)의 개수 13 | long long A6 = (N / 35); // 5, 7로 나누어떨어지는 수(= 35의 배수)의 개수 14 | long long A7 = (N / 105); // 3, 5, 7로 나누어떨어지는 수(= 105의 배수)의 개수 15 | cout << A1 + A2 + A3 - A4 - A5 - A6 + A7 << endl; 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /codes/cpp/chap07/code_7-06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N = 100; 5 | int A[109][109]; 6 | int X[1009], Y[1009], H[1009]; 7 | 8 | int main() { 9 | // 입력 10 | for (int i = 0; i < N; i++) { 11 | for (int j = 0; j < N; j++) cin >> A[i][j]; 12 | } 13 | 14 | // 답을 생성 15 | for (int i = 1; i <= 1000; i++) { 16 | X[i] = rand() % N; // 0 이상 N-1 이하의 무작위 정수 17 | Y[i] = rand() % N; // 0 이상 N-1 이하의 무작위 정수 18 | H[i] = 1; 19 | } 20 | 21 | // 출력 22 | cout << "1000" << endl; 23 | for (int i = 1; i <= 1000; i++) { 24 | cout << X[i] << " " << Y[i] << " " << H[i] << endl; 25 | } 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /editorial/chap06/cpp/answer_B41.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int X, Y; 7 | 8 | int main() { 9 | // 입력 10 | cin >> X >> Y; 11 | 12 | // 거꾸로 생각하기 13 | vector> Answer; 14 | while (X >= 2 || Y >= 2) { 15 | Answer.push_back(make_pair(X, Y)); 16 | if (X > Y) X -= Y; 17 | else Y -= X; 18 | } 19 | reverse(Answer.begin(), Answer.end()); 20 | 21 | // 출력 22 | cout << Answer.size() << endl; 23 | for (int i = 0; i < Answer.size(); i++) { 24 | cout << Answer[i].first << " " << Answer[i].second << endl; 25 | } 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /codes/java/chap06/answer_A41.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | String S = sc.next(); 10 | 11 | // 답을 구한다 12 | boolean Answer = false; 13 | for (int i = 0; i <= N - 3; i++) { 14 | if (S.charAt(i)=='R' && S.charAt(i+1)=='R' && S.charAt(i+2)=='R') Answer = true; 15 | if (S.charAt(i)=='B' && S.charAt(i+1)=='B' && S.charAt(i+2)=='B') Answer = true; 16 | } 17 | 18 | // 출력 19 | if (Answer == true) System.out.println("Yes"); 20 | else System.out.println("No"); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /editorial/chap06/cpp/answer_B40.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | long long N, A[200009]; 5 | long long cnt[109]; 6 | long long Answer = 0; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N; 11 | for (int i = 1; i <= N; i++) cin >> A[i]; 12 | 13 | // 개수를 센다 14 | for (int i = 0; i < 100; i++) cnt[i] = 0; 15 | for (int i = 1; i <= N; i++) cnt[A[i] % 100] += 1; 16 | 17 | // 답을 구한다 18 | for (int i = 1; i < 50; i++) Answer += cnt[i] * cnt[100 - i]; 19 | Answer += cnt[0] * (cnt[0] - 1LL) / 2LL; 20 | Answer += cnt[50] * (cnt[50] - 1LL) / 2LL; 21 | 22 | // 출력 23 | cout << Answer << endl; 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /editorial/chap02/cpp/answer_B07.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, T; 5 | int L[500009], R[500009]; 6 | int Answer[500009], B[500009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> T >> N; 11 | for (int i = 1; i <= N; i++) cin >> L[i] >> R[i]; 12 | 13 | // 전일 비에 더한다 14 | for (int i = 0; i <= T; i++) B[i] = 0; 15 | for (int i = 1; i <= N; i++) { 16 | B[L[i]] += 1; 17 | B[R[i]] -= 1; 18 | } 19 | 20 | // 누적 합을 구한다 21 | Answer[0] = B[0]; 22 | for (int d = 1; d <= T; d++) Answer[d] = Answer[d - 1] + B[d]; 23 | 24 | // 출력 25 | for (int d = 0; d < T; d++) cout << Answer[d] << endl; 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /editorial/chap03/python/answer_B13.py: -------------------------------------------------------------------------------- 1 | # A[l]에서 A[r]까지의 합계값 2 | def sum(l, r, S): 3 | return S[r+1] - S[l] 4 | 5 | # 입력 6 | N, K = map(int, input().split()) 7 | A = list(map(int, input().split())) 8 | 9 | # 누적 합을 구한다 10 | S = [ 0 ] * (N + 1) 11 | for i in range(1, N+1): 12 | S[i] = S[i-1] + A[i-1] 13 | 14 | # 배열 준비(R은 0번부터 시작한다는 점에 유의) 15 | R = [ None ] * N 16 | 17 | # 자벌레 알고리즘 18 | for i in range(N): 19 | if i == 0: 20 | R[i] = -1 21 | else: 22 | R[i] = R[i - 1] 23 | while R[i] < N-1 and sum(i,R[i]+1,S) <= K: 24 | R[i] += 1 25 | 26 | # 답을 구한다 27 | Answer = 0 28 | for i in range(N): 29 | Answer += (R[i] - i + 1) 30 | print(Answer) 31 | -------------------------------------------------------------------------------- /editorial/chap09/python/answer_B65.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.setrecursionlimit(1 << 30) # 재귀 상한선 없애기 3 | 4 | N, T = map(int, input().split()) 5 | T -= 1 6 | g = [[] for _ in range(N)] 7 | for _ in range(N - 1): 8 | A, B = map(int, input().split()) 9 | A -= 1 10 | B -= 1 11 | g[A].append(B) 12 | g[B].append(A) 13 | 14 | rank = [0] * N 15 | 16 | # 깊이 우선 탐색 17 | def dfs(parent: int, i: int) -> int: 18 | for j in g[i]: 19 | if j == parent: 20 | continue 21 | r = dfs(i, j) + 1 22 | if rank[i] < r: 23 | rank[i] = r 24 | return rank[i] 25 | dfs(-1, T) 26 | 27 | print(*rank) 28 | -------------------------------------------------------------------------------- /codes/cpp/chap03/answer_A11.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, X, A[100009]; 5 | 6 | // 정수 x가 몇 번째에 위치하는지 반환한다 7 | int search(int x) { 8 | int L = 1, R = N; 9 | while (L <= R) { // 탐색 범위가 없어질 때까지 계속 비교한다 10 | int M = (L + R) / 2; 11 | if (x < A[M]) R = M - 1; 12 | if (x == A[M]) return M; 13 | if (x > A[M]) L = M + 1; 14 | } 15 | return -1; // 정수 x가 존재하지 않는다(주: 이 문제의 조건에서 -1이 반환되는 일은 없다) 16 | } 17 | 18 | int main() { 19 | // 입력 20 | cin >> N >> X; 21 | for (int i = 1; i <= N; i++) cin >> A[i]; 22 | 23 | // 바이너리 서치를 수행한다 24 | int Answer = search(X); 25 | cout << Answer << endl; 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /codes/cpp/chap06/answer_A38.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int D, N; 6 | int L[10009], R[10009], H[10009], LIM[10009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> D >> N; 11 | for (int i = 1; i <= N; i++) cin >> L[i] >> R[i] >> H[i]; 12 | 13 | // 배열 초기화(1일은 24시간) 14 | for (int i = 1; i <= D; i++) LIM[i] = 24; 15 | 16 | // 상한 값을 구한다 17 | for (int i = 1; i <= N; i++) { 18 | for (int j = L[i]; j <= R[i]; j++) LIM[j] = min(LIM[j], H[i]); 19 | } 20 | 21 | // 답을 출력 22 | int Answer = 0; 23 | for (int i = 1; i <= D; i++) Answer += LIM[i]; 24 | cout << Answer << endl; 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /codes/cpp/chap06/answer_A45.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | // 입력 6 | int N; char C, A[200009]; 7 | cin >> N >> C; 8 | for (int i = 1; i <= N; i++) cin >> A[i]; 9 | 10 | // 점수 계산 11 | int score = 0; 12 | for (int i = 1; i <= N; i++) { 13 | if (A[i] == 'W') score += 0; 14 | if (A[i] == 'B') score += 1; 15 | if (A[i] == 'R') score += 2; 16 | } 17 | // 출력 18 | if (score % 3 == 0 && C == 'W') cout << "Yes" << endl; 19 | else if (score % 3 == 1 && C == 'B') cout << "Yes" << endl; 20 | else if (score % 3 == 2 && C == 'R') cout << "Yes" << endl; 21 | else cout << "No" << endl; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /codes/python/chap08/answer_A60.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | # 입력 4 | N = int(input()) 5 | A = list(map(int, input().split())) 6 | 7 | # 스택 변화 재현 8 | # (스택에는 (날짜, 주가)의 튜플을 기록한다) 9 | answer = [ None ] * N 10 | level2 = deque() 11 | for i in range(N): 12 | if i >= 1: 13 | level2.append((i, A[i - 1])) 14 | while len(level2) >= 1: 15 | kabuka = level2[-1][1] # 주식 가격은 튜플의 두 번째 요소 16 | if kabuka <= A[i]: 17 | level2.pop() 18 | else: 19 | break 20 | if len(level2) >= 1: 21 | answer[i] = level2[-1][0] # 날짜는 튜플의 첫 번째 요소 22 | else: 23 | answer[i] = -1 24 | 25 | # answer를 공백으로 구분하여 출력 26 | print(*answer) -------------------------------------------------------------------------------- /editorial/chap05/answer_B32.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // 배열 dp에 대해: dp[x]=true일 때 승리 상태, dp[x]=false일 때 패배 상태 5 | int N, K, A[109]; 6 | bool dp[100009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N >> K; 11 | for (int i = 1; i <= K; i++) cin >> A[i]; 12 | 13 | // 승자를 계산한다 14 | for (int i = 0; i <= N; i++) { 15 | dp[i] = false; 16 | for (int j = 1; j <= K; j++) { 17 | if (i >= A[j] && dp[i - A[j]] == false) { 18 | dp[i] = true; // 패배 상태로 전환할 수 있다면, 승리 상태 19 | } 20 | } 21 | } 22 | 23 | // 출력 24 | if (dp[N] == true) cout << "First" << endl; 25 | else cout << "Second" << endl; 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /codes/java/chap04/answer_A16.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int[] A = new int[N + 1]; 10 | int[] B = new int[N + 1]; 11 | for (int i = 2; i <= N; i++) A[i] = sc.nextInt(); 12 | for (int i = 3; i <= N; i++) B[i] = sc.nextInt(); 13 | 14 | // 동적 계획 알고리즘 15 | int[] dp = new int[N + 1]; 16 | dp[1] = 0; 17 | dp[2] = A[2]; 18 | for (int i = 3; i <= N; i++) { 19 | dp[i] = Math.min(dp[i - 1] + A[i], dp[i - 2] + B[i]); 20 | } 21 | 22 | // 출력 23 | System.out.println(dp[N]); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /editorial/chap05/cpp/answer_B32.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // 배열 dp에 대해: dp[x]=true일 때 승리 상태, dp[x]=false일 때 패배 상태 5 | int N, K, A[109]; 6 | bool dp[100009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N >> K; 11 | for (int i = 1; i <= K; i++) cin >> A[i]; 12 | 13 | // 승자를 계산한다 14 | for (int i = 0; i <= N; i++) { 15 | dp[i] = false; 16 | for (int j = 1; j <= K; j++) { 17 | if (i >= A[j] && dp[i - A[j]] == false) { 18 | dp[i] = true; // 패배 상태로 전환할 수 있다면, 승리 상태 19 | } 20 | } 21 | } 22 | 23 | // 출력 24 | if (dp[N] == true) cout << "First" << endl; 25 | else cout << "Second" << endl; 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /codes/cpp/chap09/answer_A65.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, A[100009], dp[100009]; 6 | vector G[100009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N; 11 | for (int i = 2; i <= N; i++) { 12 | cin >> A[i]; 13 | G[A[i]].push_back(i); // '상사→부하' 방향으로 에지를 추가 14 | } 15 | // 동적 계획 알고리즘(dp[x]는 직원 x의 부하직원 수) 16 | for (int i = N; i >= 1; i--) { 17 | dp[i] = 0; 18 | for (int j = 0; j < G[i].size(); j++) dp[i] += (dp[G[i][j]] + 1); 19 | } 20 | // 공백으로 구분해서 출력 21 | for (int i = 1; i <= N; i++) { 22 | if (i >= 2) cout << " "; 23 | cout << dp[i]; 24 | } 25 | cout << endl; 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /editorial/chap06/python/answer_B39.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, D = map(int, input().split()) 3 | X = [ None ] * N 4 | Y = [ None ] * N 5 | for i in range(N): 6 | X[i], Y[i] = map(int, input().split()) 7 | 8 | # 배열 준비 9 | # used[i]는 작업 i를 선택했는지 여부를 나타냅니다. 10 | used = [ False ] * N 11 | 12 | # 답을 구한다 13 | Answer = 0 14 | for i in range(1, D+1): 15 | maxValue = 0 # 급여의 최대치 16 | maxID = -1 # 월급이 최대가 되는 직업의 수 17 | for j in range(N): 18 | if used[j] == False and maxValue < Y[j] and X[j] <= i: 19 | maxValue = Y[j] 20 | maxID = j 21 | 22 | # 선택할 수 있는 직업이 있는 경우 23 | if maxID != -1: 24 | Answer += maxValue 25 | used[maxID] = True 26 | 27 | # 출력 28 | print(Answer) 29 | -------------------------------------------------------------------------------- /codes/java/chap05/answer_A27.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int A = sc.nextInt(); 9 | int B = sc.nextInt(); 10 | 11 | // 출력 12 | System.out.println(GCD(A, B)); 13 | } 14 | 15 | // 양의 정수 A와 B의 최대공약수를 반환하는 함수 16 | // GCD는 Greatest Common Divisor(최대공약수)를 의미 17 | static int GCD(int A, int B) { 18 | while (A >= 1 && B >= 1) { 19 | if (A >= B) { 20 | A %= B; // A의 값을 변경하는 경우 21 | } 22 | else { 23 | B %= A; // B의 값을 변경하는 경우 24 | } 25 | } 26 | if (A >= 1) { 27 | return A; 28 | } 29 | return B; 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /codes/java/chap05/answer_A32.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int A = sc.nextInt(); 10 | int B = sc.nextInt(); 11 | 12 | // 승자를 계산한다 13 | boolean[] dp = new boolean[N + 1]; 14 | for (int i = 0; i <= N; i++) { 15 | if (i >= A && dp[i-A] == false) dp[i] = true; // 승리 상태 16 | else if (i >= B && dp[i-B] == false) dp[i] = true; // 승리 상태 17 | else dp[i] = false; // 패배 상태 18 | } 19 | 20 | // 출력 21 | if (dp[N] == true) System.out.println("First"); 22 | else System.out.println("Second"); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /codes/java/chap06/answer_A43.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int L = sc.nextInt(); 10 | int[] A = new int[N + 1]; 11 | char[] B = new char[N + 1]; 12 | for (int i = 1; i <= N; i++) { 13 | A[i] = sc.nextInt(); 14 | B[i] = sc.next().charAt(0); 15 | } 16 | 17 | // 답을 구한다 18 | int Answer = 0; 19 | for (int i = 1; i <= N; i++) { 20 | if (B[i] == 'E') Answer = Math.max(Answer, L - A[i]); 21 | if (B[i] == 'W') Answer = Math.max(Answer, A[i]); 22 | } 23 | System.out.println(Answer); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /codes/cpp/chap03/answer_A13.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, K; 5 | int A[100009], R[100009]; 6 | 7 | int main() { 8 | // 입력 9 | cin >> N >> K; 10 | for (int i = 1; i <= N; i++) cin >> A[i]; 11 | 12 | // 자벌레 알고리즘 13 | for (int i = 1; i <= N - 1; i++) { 14 | // 시작 지점을 결정한다 15 | if (i == 1) R[i] = 1; 16 | else R[i] = R[i - 1]; 17 | 18 | // 한계까지 더해간다 19 | while (R[i] < N && A[R[i] + 1] - A[i] <= K) { 20 | R[i] += 1; 21 | } 22 | } 23 | 24 | // 출력(답은 최대 50억 정도가 되므로 long long 타입을 사용해야 한다) 25 | long long Answer = 0; 26 | for (int i = 1; i <= N - 1; i++) Answer += (R[i] - i); 27 | cout << Answer << endl; 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /editorial/chap06/python/answer_B38.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | S = input() 4 | 5 | # 배열 준비 6 | ret1 = [ None ] * N 7 | ret2 = [ None ] * N 8 | 9 | # 답을 구한다(전반부) 10 | streak1 = 1 # streak1은 'A가 몇 개 연속으로 이어졌는가' + 1 11 | ret1[0] = 1 12 | for i in range(N-1): 13 | if S[i] == 'A': 14 | streak1 += 1 15 | if S[i] == 'B': 16 | streak1 = 1 17 | ret1[i+1] = streak1 18 | 19 | # 답을 구한다(후반부) 20 | streak2 = 1 21 | ret2[N-1] = 1 22 | for i in reversed(range(N-1)): 23 | if S[i] == 'A': 24 | streak2 = 1 25 | if S[i] == 'B': 26 | streak2 += 1 27 | ret2[i] = streak2 28 | 29 | # 출력 30 | Answer = 0 31 | for i in range(N): 32 | Answer += max(ret1[i], ret2[i]) 33 | print(Answer) 34 | -------------------------------------------------------------------------------- /codes/cpp/chap05/answer_A35.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, A[2009]; 6 | int dp[2009][2009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N; 11 | for (int i = 1; i <= N; i++) cin >> A[i]; 12 | 13 | // 동적 계획 알고리즘 [ N번째 층 ] 14 | for (int j = 1; j <= N; j++) dp[N][j] = A[j]; 15 | 16 | // 동적 계획 알고리즘 [ 1 ~ N-1번째 층 ] 17 | for (int i = N - 1; i >= 1; i--) { 18 | for (int j = 1; j <= i; j++) { 19 | if (i % 2 == 1) dp[i][j] = max(dp[i + 1][j], dp[i + 1][j + 1]); 20 | if (i % 2 == 0) dp[i][j] = min(dp[i + 1][j], dp[i + 1][j + 1]); 21 | } 22 | } 23 | 24 | // 출력 25 | cout << dp[1][1] << endl; 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /codes/cpp/chap09/answer_A61.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, M; 6 | int A[100009], B[100009]; 7 | vector G[100009]; // 인접 리스트 8 | 9 | int main() { 10 | // 입력 11 | cin >> N >> M; 12 | for (int i = 1; i <= M; i++) { 13 | cin >> A[i] >> B[i]; 14 | G[A[i]].push_back(B[i]); // '노드 A[i]에 인접한 노드'로 B[i]를 추가 15 | G[B[i]].push_back(A[i]); // '노드 B[i]에 인접한 노드'로 A[i]를 추가 16 | } 17 | 18 | // 출력 19 | for (int i = 1; i <= N; i++) { 20 | cout << i << ": {"; 21 | for (int j = 0; j < G[i].size(); j++) { 22 | if (j >= 1) cout << ", "; 23 | cout << G[i][j]; 24 | } 25 | cout << "}" << endl; 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /codes/cpp/chap10/answer_A74.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, P[109][109]; 5 | int X[109], InversionX = 0; 6 | int Y[109], InversionY = 0; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N; 11 | for (int i = 1; i <= N; i++) { 12 | for (int j = 1; j <= N; j++) { 13 | cin >> P[i][j]; 14 | if (P[i][j] != 0) { X[i] = P[i][j]; Y[j] = P[i][j]; } 15 | } 16 | } 17 | 18 | // X의 전도 수, Y의 전도 수를 구한다 19 | for (int i = 1; i <= N; i++) { 20 | for (int j = i + 1; j <= N; j++) { 21 | if (X[i] > X[j]) InversionX += 1; 22 | if (Y[i] > Y[j]) InversionY += 1; 23 | } 24 | } 25 | 26 | // 출력 27 | cout << InversionX + InversionY << endl; 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /editorial/chap06/cpp/answer_B44.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, A[509][509]; 5 | int Q, QueryType[200009], x[200009], y[200009]; 6 | int T[509]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N; 11 | for (int i = 1; i <= N; i++) { 12 | for (int j = 1; j <= N; j++) cin >> A[i][j]; 13 | } 14 | 15 | // 배열 T 초기화 16 | for (int i = 1; i <= N; i++) T[i] = i; 17 | 18 | // 쿼리 처리 19 | cin >> Q; 20 | for (int i = 1; i <= Q; i++) { 21 | cin >> QueryType[i] >> x[i] >> y[i]; 22 | if (QueryType[i] == 1) { 23 | swap(T[x[i]], T[y[i]]); 24 | } 25 | if (QueryType[i] == 2) { 26 | cout << A[T[x[i]]][y[i]] << endl; 27 | } 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /codes/java/chap06/answer_A37.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int M = sc.nextInt(); 10 | long B = sc.nextLong(); 11 | long[] A = new long[N + 1]; 12 | long[] C = new long[M + 1]; 13 | for (int i = 1; i <= N; i++) A[i] = sc.nextLong(); 14 | for (int j = 1; j <= M; j++) C[j] = sc.nextLong(); 15 | 16 | // 답 계산 17 | long Answer = 0; 18 | for (int i = 1; i <= N; i++) Answer += A[i] * M; 19 | Answer += B * N * M; 20 | for (int j = 1; j <= M; j++) Answer += C[j] * N; 21 | 22 | // 출력 23 | System.out.println(Answer); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /codes/java/chap06/answer_A40.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int[] A = new int[N + 1]; 10 | for (int i = 1; i <= N; i++) A[i] = sc.nextInt(); 11 | 12 | // 개수를 센다 13 | long[] cnt = new long[101]; 14 | for (int i = 1; i <= 100; i++) cnt[i] = 0; 15 | for (int i = 1; i <= N; i++) cnt[A[i]] += 1; 16 | 17 | // 답을 구한다 18 | // nC3 = n * (n-1) * (n-2) / 6 을 사용한다 19 | long Answer = 0; 20 | for (int i = 1; i <= 100; i++) { 21 | Answer += cnt[i] * (cnt[i]-1) * (cnt[i]-2) / 6; 22 | } 23 | System.out.println(Answer); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /codes/python/chap06/answer_A44.py: -------------------------------------------------------------------------------- 1 | # 입력・배열 준비 2 | N, Q = map(int, input().split()) 3 | State = 1 4 | E = [ None ] * (N+2) 5 | for i in range(1, N+1): 6 | E[i] = i 7 | 8 | # 쿼리 처리 9 | for i in range(Q): 10 | Query = input().split() 11 | 12 | # [1] 변경 조작 13 | if int(Query[0]) == 1: 14 | x = int(Query[1]) 15 | y = int(Query[2]) 16 | if State == 1: 17 | E[x] = y 18 | if State == 2: 19 | E[N+1-x] = y 20 | 21 | # [2] 반전 조작 22 | if int(Query[0]) == 2: 23 | if State == 1: 24 | State = 2 25 | else: 26 | State = 1 27 | 28 | # [3] 취득 조작 29 | if int(Query[0]) == 3: 30 | x = int(Query[1]) 31 | if State == 1: 32 | print(E[x]) 33 | if State == 2: 34 | print(E[N+1-x]) 35 | -------------------------------------------------------------------------------- /editorial/chap04/cpp/answer_B22.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, A[100009], B[100009]; 6 | int dp[100009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N; 11 | for (int i = 2; i <= N; i++) cin >> A[i]; 12 | for (int i = 3; i <= N; i++) cin >> B[i]; 13 | 14 | // 배열 dp 초기화 15 | dp[1] = 0; 16 | for (int i = 2; i <= N; i++) dp[i] = 2000000000; 17 | 18 | // 동적 계획 알고리즘 19 | for (int i = 1; i <= N; i++) { 20 | if (i <= N - 1) dp[i + 1] = min(dp[i + 1], dp[i] + A[i + 1]); // i+1로 가는 경우 21 | if (i <= N - 2) dp[i + 2] = min(dp[i + 2], dp[i] + B[i + 2]); // i+2로 이동하는 경우 22 | } 23 | 24 | // 출력 25 | cout << dp[N] << endl; 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /editorial/chap08/cpp/answer_B52.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, X; 6 | char A[100009]; 7 | queue Q; 8 | 9 | int main() { 10 | // 입력 11 | cin >> N >> X; 12 | for (int i = 1; i <= N; i++) cin >> A[i]; 13 | 14 | // 시뮬레이션 15 | Q.push(X); A[X] = '@'; 16 | while (!Q.empty()) { 17 | int pos = Q.front(); Q.pop(); 18 | if (pos - 1 >= 1 && A[pos - 1] == '.') { 19 | A[pos - 1] = '@'; 20 | Q.push(pos - 1); 21 | } 22 | if (pos + 1 <= N && A[pos + 1] == '.') { 23 | A[pos + 1] = '@'; 24 | Q.push(pos + 1); 25 | } 26 | } 27 | 28 | // 출력 29 | for (int i = 1; i <= N; i++) cout << A[i]; 30 | cout << endl; 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /codes/python/chap02/answer_A10.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | A = list(map(int, input().split())) 4 | D = int(input()) 5 | L = [ None ] * D 6 | R = [ None ] * D 7 | for d in range(D): 8 | L[d], R[d] = map(int, input().split()) 9 | 10 | # P[i]를 구한다 11 | # P[0] 등으로 되어 있는 것은 배열이 0으로 시작되기 때문에 12 | P = [ None ] * N 13 | P[0] = A[0] 14 | for i in range(1, N): 15 | P[i] = max(P[i-1], A[i]) 16 | 17 | # Q[i]를 구한다 18 | # Q[N-1] 등으로 되어 있는 것은 배열이 0으로 시작되기 때문에 19 | Q = [ None ] * N 20 | Q[N-1] = A[N-1] 21 | for i in reversed(range(0,N-1)): 22 | Q[i] = max(Q[i+1], A[i]) 23 | 24 | # 각 날짜에 대해 답을 구한다 25 | # (L[d]-1)-1 등으로 되어 있는 것은 배열이 0으로 시작되기 때문에 26 | for d in range(D): 27 | print(max(P[(L[d]-1)-1], Q[(R[d]+1)-1])) 28 | -------------------------------------------------------------------------------- /codes/python/chap04/answer_A18.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, S = map(int, input().split()) 3 | A = list(map(int, input().split())) 4 | 5 | # 동적 계획 알고리즘(i=0) 6 | dp = [ [ None ] * (S + 1) for i in range(N + 1) ] 7 | dp[0][0] = True 8 | for i in range(1, S+1): 9 | dp[0][i] = False 10 | 11 | # 동적 계획 알고리즘(i=1) 12 | for i in range(1, N+1): 13 | for j in range(0,S+1): 14 | if j < A[i-1]: 15 | if dp[i-1][j] == True: 16 | dp[i][j] = True 17 | else: 18 | dp[i][j] = False 19 | 20 | if j >= A[i-1]: 21 | if dp[i-1][j] == True or dp[i-1][j-A[i-1]] == True: 22 | dp[i][j] = True 23 | else: 24 | dp[i][j] = False 25 | 26 | # 출력 27 | if dp[N][S] == True: 28 | print("Yes") 29 | else: 30 | print("No") 31 | -------------------------------------------------------------------------------- /editorial/chap04/python/answer_B23.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | X = [ None ] * N 4 | Y = [ None ] * N 5 | for i in range(N): 6 | X[i], Y[i] = map(int, input().split()) 7 | 8 | # 배열 dp 초기화 9 | dp = [ [ 1000000000.0 ] * N for i in range(2 ** N) ] 10 | 11 | # 동적 계획 알고리즘(dp[지나간 도시][현재 있는 도시]로 되어 있음) 12 | dp[0][0] = 0 13 | for i in range(2 ** N): 14 | for j in range(N): 15 | if dp[i][j] < 1000000000.0: 16 | 17 | # 도시 j에서 k로 이동하고 싶다! 18 | for k in range(N): 19 | if (i // (2 ** k)) % 2 == 0: 20 | DIST = ((1.0*(X[j]-X[k])* (X[j]-X[k]) + 1.0*(Y[j]-Y[k])*(Y[j]-Y[k])) ** 0.5) 21 | dp[i + (2 ** k)][k] = min(dp[i + (2 ** k)][k], dp[i][j] + DIST) 22 | 23 | # 출력 24 | print(dp[(2 ** N) - 1][0]) 25 | -------------------------------------------------------------------------------- /editorial/final/cpp/answer_C07.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | long long N, C[100009], S[100009]; 6 | long long Q, X[100009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N; 11 | for (int i = 1; i <= N; i++) cin >> C[i]; 12 | cin >> Q; 13 | for (int i = 1; i <= Q; i++) cin >> X[i]; 14 | 15 | // C[i] 작은 순서로 정렬 16 | sort(C + 1, C + N + 1); 17 | 18 | // 누적 합계 S[i]를 취한다 19 | // S[i]는 'i 개 상품을 구매할 때 최소 금액' 20 | S[0] = 0; 21 | for (int i = 1; i <= N; i++) S[i] = S[i - 1] + C[i]; 22 | 23 | // 질문에 답한다 24 | for (int i = 1; i <= Q; i++) { 25 | int pos = upper_bound(S, S + N + 1, X[i]) - S; 26 | cout << pos - 1 << endl; 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /codes/cpp/chap02/answer_A10.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, A[100009], P[100009], Q[100009]; 6 | int D, L[100009], R[100009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N; 11 | for (int i = 1; i <= N; i++) cin >> A[i]; 12 | cin >> D; 13 | for (int d = 1; d <= D; d++) cin >> L[d] >> R[d]; 14 | 15 | // P[i]를 구한다 16 | P[1] = A[1]; 17 | for (int i = 2; i <= N; i++) P[i] = max(P[i - 1], A[i]); 18 | 19 | // Q[i]를 구한다 20 | Q[N] = A[N]; 21 | for (int i = N - 1; i >= 1; i--) Q[i] = max(Q[i + 1], A[i]); 22 | 23 | // 각 날짜에 대해 답을 구한다 24 | for (int d = 1; d <= D; d++) { 25 | cout << max(P[L[d] - 1], Q[R[d] + 1]) << endl; 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /codes/cpp/chap05/answer_A30.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // a ÷ b를 m으로 나눈 나머지를 반환하는 함수 5 | // 함수 Power는 5.4절을 참조 6 | long long Division(long long a, long long b, long long m) { 7 | return (a * Power(b, m - 2, m)) % m; 8 | } 9 | 10 | int main() { 11 | // 입력 12 | const long long M = 1000000007; 13 | long long n, r; 14 | cin >> n >> r; 15 | 16 | // 순서 1: 분자 a를 구한다 17 | long long a = 1; 18 | for (int i = 1; i <= n; i++) a = (a * i) % M; 19 | 20 | // 순서 2: 분모 b를 구한다 21 | long long b = 1; 22 | for (int i = 1; i <= r; i++) b = (b * i) % M; 23 | for (int i = 1; i <= n - r; i++) b = (b * i) % M; 24 | 25 | // 순서 3: 답을 구한다 26 | cout << Division(a, b, M) << endl; 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /codes/java/chap05/answer_A26.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int Q = sc.nextInt(); 9 | int[] X = new int[Q + 1]; 10 | for (int i = 1; i <= Q; i++) X[i] = sc.nextInt(); 11 | 12 | // 출력 13 | for (int i = 1; i <= Q; i++) { 14 | boolean Answer = isPrime(X[i]); 15 | if (Answer == true) System.out.println("Yes"); 16 | if (Answer == false) System.out.println("No"); 17 | } 18 | } 19 | 20 | // x가 소수일 때 true, 소수가 아닐 때 false를 반환하는 함수 21 | static boolean isPrime(int x) { 22 | for (int i = 2; i * i <= x; i++) { 23 | if (x % i == 0) return false; 24 | } 25 | return true; 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /codes/cpp/chap04/answer_A25.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | long long H, W; 5 | char c[39][39]; 6 | long long dp[39][39]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> H >> W; 11 | for (int i = 1; i <= H; i++) { 12 | for (int j = 1; j <= W; j++) cin >> c[i][j]; 13 | } 14 | 15 | // 동적 계획 알고리즘 16 | for (int i = 1; i <= H; i++) { 17 | for (int j = 1; j <= W; j++) { 18 | if (i == 1 && j == 1) { 19 | dp[i][j] = 1; 20 | } 21 | else { 22 | dp[i][j] = 0; 23 | if (i >= 2 && c[i - 1][j] == '.') dp[i][j] += dp[i - 1][j]; 24 | if (j >= 2 && c[i][j - 1] == '.') dp[i][j] += dp[i][j - 1]; 25 | } 26 | } 27 | } 28 | 29 | // 출력 30 | cout << dp[H][W] << endl; 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /codes/python/chap03/answer_A12.py: -------------------------------------------------------------------------------- 1 | # 답이 x 이하인지 판정하고 Yes라면 true, No라면 false를 반환하는 함수 2 | def check(x, N, K, A): 3 | sum = 0 4 | for i in range(N): 5 | sum += x // A[i] # 'x÷A[i]' 소수점 이하 자르기 6 | 7 | if sum >= K: 8 | return True 9 | return False 10 | 11 | # 입력 12 | N, K = map(int, input().split()) 13 | A = list(map(int, input().split())) 14 | 15 | # 바이너리 서치 16 | # Left는 탐색 범위의 왼쪽 끝, Right는 탐색 범위의 오른쪽 끝을 나타낸다 17 | Left = 1 18 | Right = 10 ** 9 19 | while Left < Right: 20 | Mid = (Left + Right) // 2 21 | Answer = check(Mid, N, K, A) 22 | 23 | if Answer == False: 24 | Left = Mid + 1 # 답이 Mid+1 이상임을 알 수 있다 25 | if Answer == True: 26 | Right = Mid # 답이 Mid 이하임을 알 수 있다 27 | 28 | # 출력(이때, Left=Right가 된다) 29 | print(Left) 30 | -------------------------------------------------------------------------------- /codes/python/chap05/answer_A30.py: -------------------------------------------------------------------------------- 1 | # a의 b제곱을 m으로 나눈 나머지를 반환하는 함수 2 | def Power(a, b, m): 3 | p = a 4 | Answer = 1 5 | for i in range(30): 6 | wari = 2 ** i 7 | if (b // wari) % 2 == 1: 8 | Answer = (Answer * p) % m # a의 2^i 제곱을 곱할 때 9 | p = (p * p) % m 10 | return Answer 11 | 12 | # a÷b를 m으로 나눈 나머지를 반환하는 함수 13 | def Division(a, b, m): 14 | return (a * Power(b, m - 2, m)) % m 15 | 16 | # 입력 등 17 | n, r = map(int, input().split()) 18 | M = 1000000007 19 | 20 | # 1단계: 분자 찾기 21 | a = 1 22 | for i in range(1, n + 1): 23 | a = (a * i) % M 24 | 25 | # 2단계: 분모 찾기 26 | b = 1 27 | for i in range(1, r+1): 28 | b = (b * i) % M 29 | for i in range(1, n-r+1): 30 | b = (b * i) % M 31 | 32 | # 3단계: 답을 구한다 33 | print(Division(a, b, M)) 34 | -------------------------------------------------------------------------------- /codes/python/chap05/answer_A34.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, X, Y = map(int, input().split()) 3 | A = list(map(int, input().split())) 4 | 5 | # Grundy 수치를 구하다 6 | # 변수 grundy[i]: 돌이 i개일 때의 Grundy 수 7 | # 변수 Transit[i]: Grundy 수가 i가 되도록 전이할 수 있는가 8 | grundy = [ None ] * 100001 9 | for i in range(100001): 10 | Transit = [False, False, False] 11 | if i >= X: 12 | Transit[grundy[i-X]] = True 13 | if i >= Y: 14 | Transit[grundy[i-Y]] = True 15 | 16 | if Transit[0] == False: 17 | grundy[i] = 0 18 | elif Transit[1] == False: 19 | grundy[i] = 1 20 | else: 21 | grundy[i] = 2 22 | 23 | # 출력 24 | XOR_Sum = 0 25 | for i in range(N): 26 | XOR_Sum = (XOR_Sum ^ grundy[A[i]]) 27 | if XOR_Sum >= 1: 28 | print("First") 29 | else: 30 | print("Second") 31 | -------------------------------------------------------------------------------- /editorial/chap04/python/answer_B24.py: -------------------------------------------------------------------------------- 1 | import bisect 2 | 3 | # 배열 A의 가장 긴 증가부 분절(LIS)의 길이를 계산한다 4 | # 배열 dp를 사용하지 않는 구현방법을 이용하고 있다 5 | def Get_LISvalue(A): 6 | LEN = 0 7 | L = [] 8 | for i in range(N): 9 | pos = bisect.bisect_left(L, A[i]) 10 | if pos == LEN: 11 | L.append(A[i]) 12 | LEN += 1 13 | else: 14 | L[pos] = A[i] 15 | return LEN 16 | 17 | # 입력 18 | N = int(input()) 19 | X = [ None ] * N 20 | Y = [ None ] * N 21 | for i in range(N): 22 | X[i], Y[i] = map(int, input().split()) 23 | 24 | # 정렬 25 | tmp = [] 26 | for i in range(N): 27 | tmp.append([X[i], -Y[i]]) 28 | tmp.sort() 29 | 30 | # LIS를 찾아야 하는 배열은? 31 | A = [] 32 | for i in range(N): 33 | A.append(-tmp[i][1]) 34 | 35 | # 출력 36 | print(Get_LISvalue(A)) 37 | -------------------------------------------------------------------------------- /codes/cpp/chap06/code_6-01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, L[300009], R[300009]; 6 | 7 | int main() { 8 | // 입력 9 | cin >> N; 10 | for (int i = 1; i <= N; i++) cin >> L[i] >> R[i]; 11 | 12 | // 종료 시각이 빠른 것부터 탐욕적으로 취해 간다(CurrentTime은 현재 시각) 13 | int CurrentTime = 0, Answer = 0; 14 | while (true) { 15 | int Min_EndTime = 999999; // 다음으로 선택할 영화의 종료 시각 16 | for (int i = 1; i <= N; i++) { 17 | if (L[i] < CurrentTime) continue; 18 | Min_EndTime = min(Min_EndTime, R[i]); 19 | } 20 | 21 | // 다음으로 선택할 영화가 있다/없다에 대응해 처리를 수행한다 22 | if (Min_EndTime == 999999) break; 23 | CurrentTime = Min_EndTime; Answer += 1; 24 | } 25 | cout << Answer << endl; 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /codes/python/chap03/answer_A14.py: -------------------------------------------------------------------------------- 1 | import bisect 2 | import sys 3 | 4 | # 입력 5 | N, K = map(int, input().split()) 6 | A = list(map(int, input().split())) 7 | B = list(map(int, input().split())) 8 | C = list(map(int, input().split())) 9 | D = list(map(int, input().split())) 10 | 11 | # 배열 P를 작성 12 | P = [] 13 | for x in range(N): 14 | for y in range(N): 15 | P.append(A[x] + B[y]) 16 | 17 | # 배열 Q를 작성 18 | Q = [] 19 | for z in range(N): 20 | for w in range(N): 21 | Q.append(C[z] + D[w]) 22 | 23 | # 배열 Q를 오름차순으로 정렬 24 | Q.sort() 25 | 26 | # 바이너리 서치 27 | for i in range(len(P)): 28 | pos1 = bisect.bisect_left(Q, K-P[i]) 29 | if pos1 2 | using namespace std; 3 | 4 | // 입력으로 주어지는 변수 5 | int D, X, A[200009]; 6 | int Q, S[200009], T[200009]; 7 | 8 | // 각 일별 주가 9 | int Price[200009]; 10 | 11 | int main() { 12 | // 입력 13 | cin >> D >> X; 14 | for (int i = 2; i <= D; i++) cin >> A[i]; 15 | cin >> Q; 16 | for (int i = 1; i <= Q; i++) cin >> S[i] >> T[i]; 17 | 18 | // 각 일별 주가 구하기(누적 합계) 19 | Price[1] = X; 20 | for (int i = 2; i <= D; i++) Price[i] = Price[i - 1] + A[i]; 21 | 22 | // 답 출력하기 23 | for (int i = 1; i <= Q; i++) { 24 | if (Price[S[i]] > Price[T[i]]) cout << S[i] << endl; 25 | else if (Price[S[i]] < Price[T[i]]) cout << T[i] << endl; 26 | else cout << "Same" << endl; 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /codes/cpp/chap05/code_5-02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int Q, X[10009], N = 300000; // X[i] <= 300000이므로 300000 이하의 소수를 열거 5 | bool Deleted[300009]; // 정수 x가 지워진 경우에 한해 Deleted[x]=true 6 | 7 | int main() { 8 | // 입력, 배열 초기화 9 | cin >> Q; 10 | for (int i = 1; i <= Q; i++) cin >> X[i]; 11 | for (int i = 2; i <= N; i++) Deleted[i] = false; 12 | 13 | // 에라토스테네스의 체(i는 √N 이하의 가장 큰 정수까지 반복한다) 14 | for (int i = 2; i * i <= N; i++) { 15 | if (Deleted[i] == true) continue; 16 | for (int j = i * 2; j <= N; j += i) Deleted[j] = true; 17 | } 18 | 19 | // 출력 20 | for (int i = 1; i <= Q; i++) { 21 | if (Deleted[X[i]] == false) cout << "Yes" << endl; 22 | else cout << "No" << endl; 23 | } 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /codes/java/chap05/answer_A29.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | long a = sc.nextLong(); 9 | long b = sc.nextLong(); 10 | 11 | // 출력(Answer는 현재 칠판의 수) 12 | System.out.println(Power(a, b, 1000000007)); 13 | } 14 | 15 | // a의 b제곱을 m으로 나눈 나머지를 반환하는 함수 16 | // 변수 p는 a^1 → a^2 → a^4 → a^8 → a^16 → ・・・으로 변화 17 | static long Power(long a, long b, long m) { 18 | long p = a, Answer = 1; 19 | for (int i = 0; i < 30; i++) { 20 | int wari = (1 << i); 21 | if ((b / wari) % 2 == 1) { 22 | Answer = (Answer * p) % m; // 'a의 2i승'을 곱할 때 23 | } 24 | p = (p * p) % m; 25 | } 26 | return Answer; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /codes/java/chap10/answer_A71.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | // 입력(책과 달리 A[i], B[i]는 0-indexed로 입력합니다.) 6 | Scanner sc = new Scanner(System.in); 7 | int N = sc.nextInt(); 8 | Integer[] A = new Integer[N]; 9 | Integer[] B = new Integer[N]; 10 | for (int i = 0; i < N; i++) { 11 | A[i] = sc.nextInt(); 12 | } 13 | for (int i = 0; i < N; i++) { 14 | B[i] = sc.nextInt(); 15 | } 16 | 17 | // 배열 정렬 18 | Arrays.sort(A); 19 | Arrays.sort(B, Collections.reverseOrder()); 20 | 21 | // 해답을 찾아 출력 22 | int answer = 0; 23 | for (int i = 0; i < N; i++) { 24 | answer += A[i] * B[i]; 25 | } 26 | System.out.println(answer); 27 | } 28 | } -------------------------------------------------------------------------------- /codes/python/chap10/answer_A77.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, L = map(int, input().split()) 3 | K = int(input()) 4 | A = list(map(int, input().split())) 5 | 6 | # 점수의 최대값이 x 이상인지 판단하는 함수 7 | def check(x): 8 | cnt = 0 # 현재 시점에서 몇 번을 자른 것인지 표시 9 | last_kireme = 0 # 마지막으로 자른 위치를 나타낸다 10 | for i in range(N): 11 | if A[i] - last_kireme >= x and L - A[i] >= x: 12 | cnt += 1 13 | last_kireme = A[i] 14 | return cnt >= K 15 | 16 | # 바이너리 서치(left: 현재 상한 / right: 현재 하한) 17 | left, right = 1, 10 ** 9 18 | while left < right: 19 | mid = (left + right + 1) // 2 20 | answer = check(mid) 21 | if answer == False: 22 | right = mid - 1 # 답이 전반 부분으로 좁혀진다 23 | else: 24 | left = mid # 답이 후반 부분으로 좁혀진다 25 | 26 | # 출력 27 | print(left) -------------------------------------------------------------------------------- /editorial/chap09/cpp/answer_B61.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, M, A[100009], B[100009]; 6 | vector G[100009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N >> M; 11 | for (int i = 1; i <= M; i++) { 12 | cin >> A[i] >> B[i]; 13 | G[A[i]].push_back(B[i]); // '노드 A[i]에 인접한 노드'로 B[i]를 추가 14 | G[B[i]].push_back(A[i]); // '노드 B[i]에 인접한 노드'로 A[i]를 추가 15 | } 16 | 17 | // 차수(= 친구 수)가 최대가 되는 학생의 수를 구한다 18 | int MaxFriends = 0; // 최대 친구 수 19 | int MaxID = 0; // 번호 20 | for (int i = 1; i <= N; i++) { 21 | if (MaxFriends < (int)G[i].size()) { 22 | MaxFriends = (int)G[i].size(); 23 | MaxID = i; 24 | } 25 | } 26 | 27 | // 출력 28 | cout << MaxID << endl; 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /codes/java/chap01/answer_A03.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int K = sc.nextInt(); 10 | int[] P = new int[N + 1]; 11 | int[] Q = new int[N + 1]; 12 | for (int i = 1; i <= N; i++) P[i] = sc.nextInt(); 13 | for (int i = 1; i <= N; i++) Q[i] = sc.nextInt(); 14 | 15 | // 완전 탐색(Answer는 '합계가 K가 되는 선택 방법을 발견했는가'를 나타냄) 16 | boolean Answer = false; 17 | for (int x = 1; x <= N; x++) { 18 | for (int y = 1; y <= N; y++) { 19 | if (P[x] + Q[y] == K) Answer = true; 20 | } 21 | } 22 | 23 | // 출력 24 | if (Answer == true) System.out.println("Yes"); 25 | else System.out.println("No"); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /codes/java/chap04/answer_A22.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int[] A = new int[N + 1]; 10 | int[] B = new int[N + 1]; 11 | for (int i = 1; i <= N - 1; i++) A[i] = sc.nextInt(); 12 | for (int i = 1; i <= N - 1; i++) B[i] = sc.nextInt(); 13 | 14 | // 배열 초기화 15 | int[] dp = new int[N + 1]; 16 | dp[1] = 0; 17 | for (int i = 2; i <= N; i++) dp[i] = -1000000000; 18 | 19 | // 동적 계획 알고리즘 20 | for (int i = 1; i <= N - 1; i++) { 21 | dp[A[i]] = Math.max(dp[A[i]], dp[i] + 100); 22 | dp[B[i]] = Math.max(dp[B[i]], dp[i] + 150); 23 | } 24 | 25 | // 출력 26 | System.out.println(dp[N]); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /codes/java/chap06/answer_A45.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | char C = sc.next().charAt(0); 10 | String A = sc.next(); 11 | 12 | // 점수 계산 13 | int score = 0; 14 | for (int i = 0; i < N; i++) { 15 | if (A.charAt(i) == 'W') score += 0; 16 | if (A.charAt(i) == 'B') score += 1; 17 | if (A.charAt(i) == 'R') score += 2; 18 | } 19 | 20 | // 출력 21 | if (score % 3 == 0 && C == 'W') System.out.println("Yes"); 22 | else if (score % 3 == 1 && C == 'B') System.out.println("Yes"); 23 | else if (score % 3 == 2 && C == 'R') System.out.println("Yes"); 24 | else System.out.println("No"); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /codes/python/chap09/answer_A63.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | # 입력 4 | N, M = map(int, input().split()) 5 | edges = [ list(map(int, input().split())) for i in range(M) ] 6 | 7 | # 인접 리스트 생성 8 | G = [ list() for i in range(N + 1) ] 9 | for a, b in edges: 10 | G[a].append(b) 11 | G[b].append(a) 12 | 13 | # 너비 우선 탐색의 초기화(dist[i] = ? 가 아닌 dist[i] = -1로 초기화됨을 주의) 14 | dist = [ -1 ] * (N + 1) 15 | dist[1] = 0 16 | Q = deque() 17 | Q.append(1) 18 | 19 | # 너비 우선 탐색 20 | while len(Q) >= 1: 21 | pos = Q.popleft() # 큐 Q의 첫 번째 요소를 제거하고 그 값을 pos에 대입 22 | for nex in G[pos]: 23 | if dist[nex] == -1: 24 | dist[nex] = dist[pos] + 1 25 | Q.append(nex) 26 | 27 | # 정점 1에서 각 정점까지의 최단 거리를 출력 28 | for i in range(1, N + 1): 29 | print(dist[i]) -------------------------------------------------------------------------------- /codes/cpp/chap08/answer_A57.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, Q, A[100009], X[100009], Y[100009]; 5 | int dp[32][100009]; 6 | 7 | int main() { 8 | // 입력 9 | cin >> N >> Q; 10 | for (int i = 1; i <= N; i++) cin >> A[i]; 11 | for (int j = 1; j <= Q; j++) cin >> X[j] >> Y[j]; 12 | 13 | // 사전 계산 14 | for (int i = 1; i <= N; i++) dp[0][i] = A[i]; 15 | for (int d = 1; d <= 29; d++) { 16 | for (int i = 1; i <= N; i++) dp[d][i] = dp[d - 1][dp[d - 1][i]]; 17 | } 18 | 19 | // 쿼리 처리 20 | for (int j = 1; j <= Q; j++) { 21 | int CurrentPlace = X[j]; 22 | for (int d = 29; d >= 0; d--) { 23 | if ((Y[j] / (1 << d)) % 2 != 0) CurrentPlace = dp[d][CurrentPlace]; 24 | } 25 | cout << CurrentPlace << endl; 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /editorial/chap04/python/answer_B17.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | H = list(map(int, input().split())) 4 | 5 | # 배열 준비 6 | dp = [ None ] * N 7 | 8 | # 동적 계획 알고리즘 9 | dp[0] = 0 10 | dp[1] = abs(H[0] - H[1]) 11 | for i in range(2, N): 12 | dp[i] = min(dp[i-1] + abs(H[i-1]-H[i]), dp[i-2] + abs(H[i-2]-H[i])) 13 | 14 | # 답의 복원 15 | # 변수 Place는 현재 위치(목표부터 진행한다) 16 | Answer = [] 17 | Place = N-1 18 | while True: 19 | Answer.append(Place + 1) 20 | if Place == 0: 21 | break 22 | 23 | # 어디에서 방 Place로 이동하는 것이 최적인지 구한다 24 | if dp[Place-1] + abs(H[Place-1]-H[Place]) == dp[Place]: 25 | Place = Place - 1 26 | else: 27 | Place = Place - 2 28 | Answer.reverse() 29 | 30 | # 답을 출력 31 | Answer2 = [str(i) for i in Answer] 32 | print(len(Answer)) 33 | print(" ".join(Answer2)) 34 | -------------------------------------------------------------------------------- /codes/java/chap02/answer_A06.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int Q = sc.nextInt(); 10 | int[] A = new int[N + 1]; 11 | int[] S = new int[N + 1]; 12 | int[] L = new int[Q + 1]; 13 | int[] R = new int[Q + 1]; 14 | for (int i = 1; i <= N; i++) { 15 | A[i] = sc.nextInt(); 16 | } 17 | for (int j = 1; j <= Q; j++) { 18 | L[j] = sc.nextInt(); 19 | R[j] = sc.nextInt(); 20 | } 21 | 22 | // 누적 합 계산 23 | S[0] = 0; 24 | for (int i = 1; i <= N; i++) S[i] = S[i - 1] + A[i]; 25 | 26 | // 질문에 답한다 27 | for (int j = 1; j <= Q; j++) { 28 | System.out.println(S[R[j]] - S[L[j] - 1]); 29 | } 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /codes/java/chap05/answer_A35.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int[] A = new int[N + 1]; 10 | for (int i = 1; i <= N; i++) A[i] = sc.nextInt(); 11 | 12 | // 동적 계획 알고리즘(N 단계) 13 | int[][] dp = new int[N + 1][N + 1]; 14 | for (int j = 1; j <= N; j++) dp[N][j] = A[j]; 15 | 16 | // 동적 계획 알고리즘 [ 1 ~ N-1번째 층 ] 17 | for (int i = N - 1; i >= 1; i--) { 18 | for (int j = 1; j <= i; j++) { 19 | if (i % 2 == 1) dp[i][j] = Math.max(dp[i+1][j], dp[i+1][j+1]); 20 | if (i % 2 == 0) dp[i][j] = Math.min(dp[i+1][j], dp[i+1][j+1]); 21 | } 22 | } 23 | 24 | // 출력 25 | System.out.println(dp[1][1]); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /editorial/chap06/python/answer_B37.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | 4 | # 10의 N 제곱 찾기 5 | Power10 = [ None ] * 17 6 | for i in range(17): 7 | Power10[i] = 10 ** i 8 | 9 | # R[i][j]의 값 계산 10 | R = [ [ None ] * 10 for i in range(17) ] 11 | for i in range(16): 12 | # 아래에서 i 번째 자리의 숫자를 찾습니다. 13 | Digit = (N // Power10[i]) % 10; 14 | 15 | # R[i][j] 값 구하기 16 | for j in range(10): 17 | if j < Digit: 18 | R[i][j] = (N // Power10[i + 1] + 1) * Power10[i] 19 | if j == Digit: 20 | R[i][j] = (N // Power10[i + 1]) * Power10[i] + (N % Power10[i]) + 1 21 | if j > Digit: 22 | R[i][j] = (N // Power10[i + 1]) * Power10[i] 23 | 24 | # 답을 구한다 25 | Answer = 0 26 | for i in range(16): 27 | for j in range(10): 28 | Answer += j * R[i][j] 29 | 30 | # 출력 31 | print(Answer) 32 | -------------------------------------------------------------------------------- /codes/cpp/chap09/answer_A69.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int N; char c[159][159]; 7 | MaximumFlow Z; // MaximumFlow 클래스는 9.8절 참조 8 | 9 | int main() { 10 | // 입력 11 | cin >> N; 12 | for (int i = 1; i <= N; i++) { 13 | for (int j = 1; j <= N; j++) cin >> c[i][j]; 14 | } 15 | 16 | // 클래스를 구성한다 17 | Z.init(2 * N + 2); 18 | for (int i = 1; i <= N; i++) { 19 | for (int j = 1; j <= N; j++) { 20 | if (c[i][j] == '#') Z.add_edge(i, N + j, 1); 21 | } 22 | } 23 | for (int i = 1; i <= N; i++) { 24 | Z.add_edge(2 * N + 1, i, 1); // 's → 파란색'의 에지 25 | Z.add_edge(N + i, 2 * N + 2, 1); // '빨간색 → t'의 에지 26 | } 27 | // 답 출력 28 | cout << Z.max_flow(2 * N + 1, 2 * N + 2) << endl; 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /codes/java/chap08/answer_A51.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | // 입력 6 | Scanner sc = new Scanner(System.in); 7 | int Q = sc.nextInt(); 8 | int[] queryType = new int[Q + 1]; 9 | String[] x = new String[Q + 1]; 10 | for (int i = 1; i <= Q; i++) { 11 | queryType[i] = sc.nextInt(); 12 | if (queryType[i] == 1) { 13 | x[i] = sc.next(); 14 | } 15 | } 16 | 17 | // 쿼리 처리 18 | Stack S = new Stack<>(); 19 | for (int i = 1; i <= Q; i++) { 20 | if (queryType[i] == 1) { 21 | S.push(x[i]); 22 | } 23 | if (queryType[i] == 2) { 24 | System.out.println(S.peek()); 25 | } 26 | if (queryType[i] == 3) { 27 | S.pop(); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /codes/python/chap10/answer_A75.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | problems = [ list(map(int, input().split())) for i in range(N) ] # Tuple (T[i], D[i])이 N 개씩 정렬된 배열이 된다. 4 | 5 | # D[i]의 오름차순으로 정렬한다 6 | problems.sort(key = lambda p: p[1]) 7 | 8 | # 동적 계획 알고리즘:사전 준비 9 | MAX_D = max(map(lambda p: p[1], problems)) # D[i]의 최대값(책 속 코드에서는 '1440'이라는 상수를 사용하지만, 여기서는 MAX_D를 대신 사용하기로 한다) 10 | dp = [ [ -(10 ** 10) ] * (MAX_D + 1) for i in range(N + 1) ] 11 | 12 | # 동적 계획 알고리즘 13 | dp[0][0] = 0 14 | for i in range(N): 15 | t, d = problems[i] # 책 속의 T[i], D[i]에 대응 16 | for j in range(MAX_D + 1): 17 | if j > d or j < t: 18 | dp[i + 1][j] = dp[i][j] 19 | else: 20 | dp[i + 1][j] = max(dp[i][j], dp[i][j - t] + 1) 21 | 22 | # 답을 출력 23 | answer = max(dp[N]) 24 | print(answer) -------------------------------------------------------------------------------- /editorial/chap08/python/answer_B59.py: -------------------------------------------------------------------------------- 1 | siz = 1 << 18 2 | dat = [0] * (siz * 2) 3 | 4 | # 대입 seg[i] = v 5 | def update(i: int, v: int) -> None: 6 | i += siz 7 | dat[i] = v 8 | while i > 1: 9 | i >>= 1 10 | dat[i] = dat[i * 2] + dat[i * 2 + 1] 11 | 12 | # sum(seg[l], seg[l + 1], ..., seg[r - 1])을 구한다 13 | def query(l: int, r: int) -> int: 14 | l += siz 15 | r += siz 16 | answer = 0 17 | while l < r: 18 | if l & 1: 19 | answer += dat[l] 20 | l += 1 21 | if r & 1: 22 | r -= 1 23 | answer += dat[r] 24 | l >>= 1 25 | r >>= 1 26 | return answer 27 | 28 | # 입력 29 | N = int(input()) 30 | A = list(map(int, input().split())) 31 | 32 | # 답을 구한다 33 | Answer = 0 34 | for a in A: 35 | Answer += query(a + 1, siz) 36 | update(a, 1) 37 | 38 | # 출력 39 | print(Answer) 40 | -------------------------------------------------------------------------------- /codes/java/chap08/answer_A52.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | // 입력 6 | Scanner sc = new Scanner(System.in); 7 | int Q = sc.nextInt(); 8 | int[] queryType = new int[Q + 1]; 9 | String[] x = new String[Q + 1]; 10 | for (int i = 1; i <= Q; i++) { 11 | queryType[i] = sc.nextInt(); 12 | if (queryType[i] == 1) { 13 | x[i] = sc.next(); 14 | } 15 | } 16 | 17 | // 쿼리 처리 18 | Queue T = new LinkedList<>(); 19 | for (int i = 1; i <= Q; i++) { 20 | if (queryType[i] == 1) { 21 | T.add(x[i]); 22 | } 23 | if (queryType[i] == 2) { 24 | System.out.println(T.peek()); 25 | } 26 | if (queryType[i] == 3) { 27 | T.remove(); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /codes/java/chap08/answer_A53.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | // 입력 6 | Scanner sc = new Scanner(System.in); 7 | int Q = sc.nextInt(); 8 | int[] queryType = new int[Q + 1]; 9 | int[] x = new int[Q + 1]; 10 | for (int i = 1; i <= Q; i++) { 11 | queryType[i] = sc.nextInt(); 12 | if (queryType[i] == 1) { 13 | x[i] = sc.nextInt(); 14 | } 15 | } 16 | 17 | // 쿼리 처리 18 | Queue T = new PriorityQueue<>(); 19 | for (int i = 1; i <= Q; i++) { 20 | if (queryType[i] == 1) { 21 | T.add(x[i]); 22 | } 23 | if (queryType[i] == 2) { 24 | System.out.println(T.peek()); 25 | } 26 | if (queryType[i] == 3) { 27 | T.remove(); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /editorial/chap08/cpp/answer_B53.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | long long N, D; 7 | long long X[200009], Y[200009]; 8 | vector G[375]; // G[i]는 i 일째부터 시작하는 직업의 급여 목록이다 9 | long long Answer = 0; 10 | 11 | int main() { 12 | // 입력 13 | cin >> N >> D; 14 | for (int i = 1; i <= N; i++) { 15 | cin >> X[i] >> Y[i]; 16 | G[X[i]].push_back(Y[i]); 17 | } 18 | 19 | // 답을 구한다 20 | priority_queue Q; 21 | for (int i = 1; i <= D; i++) { 22 | // i 일차부터 시작하는 작업을 대기열에 추가한다 23 | for (int j : G[i]) Q.push(j); 24 | 25 | // 할 일을 선택하고 해당 작업을 대기열에서 삭제한다 26 | if (!Q.empty()) { 27 | Answer += Q.top(); 28 | Q.pop(); 29 | } 30 | } 31 | 32 | // 출력 33 | cout << Answer << endl; 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /codes/cpp/chap06/answer_A44.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, Q, State = 1; 5 | int E[200009]; 6 | 7 | int main() { 8 | // 입력 → 배열 준비 9 | cin >> N >> Q; 10 | for (int i = 1; i <= N; i++) E[i] = i; 11 | 12 | // 쿼리 처리 13 | for (int i = 1; i <= Q; i++) { 14 | int Type, x, y; cin >> Type; 15 | 16 | // [1] 변경 조작 17 | if (Type == 1) { 18 | cin >> x >> y; 19 | if (State == 1) E[x] = y; 20 | if (State == 2) E[N + 1 - x] = y; 21 | } 22 | 23 | // [2] 반전 조작 24 | if (Type == 2) { 25 | if (State == 1) State = 2; 26 | else State = 1; 27 | } 28 | 29 | // [3] 취득 조작 30 | if (Type == 3) { 31 | cin >> x; 32 | if (State == 1) cout << E[x] << endl; 33 | if (State == 2) cout << E[N + 1 - x] << endl; 34 | } 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /codes/java/chap05/answer_A28.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | char[] T = new char[N + 1]; 10 | long[] A = new long[N + 1]; 11 | for (int i = 1; i <= N; i++) { 12 | T[i] = sc.next().charAt(0); 13 | A[i] = sc.nextInt(); 14 | } 15 | 16 | // 출력(Answer는 현재 칠판의 수) 17 | long Answer = 0; 18 | for (int i = 1; i <= N; i++) { 19 | if (T[i] == '+') Answer += A[i]; 20 | if (T[i] == '-') Answer -= A[i]; 21 | if (T[i] == '*') Answer *= A[i]; 22 | 23 | // 뺄셈의 답이 0 미만이 된 경우 24 | if (Answer < 0) Answer += 10000; 25 | 26 | // 여기에서 나머지를 구한다! 27 | Answer %= 10000; 28 | System.out.println(Answer); 29 | } 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /editorial/chap09/python/answer_B62.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.setrecursionlimit(1 << 20) # 재귀 상한이 기본적으로 1000으로 설정되어 있으므로 변경한다 3 | 4 | # 입력 5 | N, M = map(int, input().split()) 6 | g = [[] for _ in range(N)] 7 | for i in range(M): 8 | A, B = map(int, input().split()) 9 | A -= 1 10 | B -= 1 11 | g[A].append(B) 12 | g[B].append(A) 13 | 14 | # 깊이 우선 탐색 15 | visited = [False] * (N + 1) 16 | path = [] 17 | 18 | def dfs(i: int): 19 | path.append(i) 20 | # 결승점에 도착한 경우 21 | if i == N - 1: 22 | # 답을 출력하고 종료 23 | for x in path: 24 | print(x + 1) # 1-indexed로 변경 25 | exit(0) 26 | 27 | # 그 외의 경우 28 | visited[i] = True 29 | for j in g[i]: 30 | if not visited[j]: 31 | dfs(j) 32 | path.pop() 33 | 34 | dfs(0) 35 | -------------------------------------------------------------------------------- /codes/java/chap06/answer_A39.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int[][] A = new int[N][2]; 10 | for (int i = 1; i <= N; i++) { 11 | A[i - 1][0] = sc.nextInt(); 12 | A[i - 1][1] = sc.nextInt(); 13 | } 14 | 15 | // 배열 A를 종료 시간(A[x][1])의 오름차순으로 정렬 16 | Arrays.sort(A, (a1, a2) -> Integer.compare(a1[1], a2[1])); 17 | 18 | // 종료 시각이 빠른 것부터 탐욕적으로 취해 간다(CurrentTime은 현재 시각) 19 | int CurrentTime = 0; 20 | int Answer = 0; 21 | for (int i = 1; i <= N; i++) { 22 | if (CurrentTime <= A[i - 1][0]) { 23 | CurrentTime = A[i - 1][1]; 24 | Answer += 1; 25 | } 26 | } 27 | 28 | // 출력 29 | System.out.println(Answer); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /editorial/chap02/python/answer_B09.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | A = [ None ] * N 4 | B = [ None ] * N 5 | C = [ None ] * N 6 | D = [ None ] * N 7 | for i in range(N): 8 | A[i], B[i], C[i], D[i] = map(int, input().split()) 9 | 10 | # 각 용지에 대해 +1/-1을 더한다 11 | T = [ [ 0 ] * 1501 for i in range(1501) ] 12 | for i in range(N): 13 | T[A[i]][B[i]] += 1 14 | T[A[i]][D[i]] -= 1 15 | T[C[i]][B[i]] -= 1 16 | T[C[i]][D[i]] += 1 17 | 18 | # 누적 합을 구한다 19 | for i in range(0, 1501): 20 | for j in range(1, 1501): 21 | T[i][j] = T[i][j-1] + T[i][j] 22 | for i in range(1, 1501): 23 | for j in range(0, 1501): 24 | T[i][j] = T[i-1][j] + T[i][j] 25 | 26 | # 면적 계산 27 | Answer = 0 28 | for i in range(1501): 29 | for j in range(1501): 30 | if T[i][j] >= 1: 31 | Answer += 1 32 | 33 | # 출력 34 | print(Answer) 35 | -------------------------------------------------------------------------------- /codes/cpp/chap06/answer_A42.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, K; 6 | int A[309], B[309]; 7 | 8 | // 정수의 쌍(a, b)가 결정되었을 때 참가 가능한 학생 수를 반환하는 함수 9 | int GetScore(int a, int b) { 10 | int cnt = 0; 11 | for (int i = 1; i <= N; i++) { 12 | if (a <= A[i] && A[i] <= a + K && b <= B[i] && B[i] <= b + K) { 13 | cnt += 1; 14 | } 15 | } 16 | return cnt; 17 | } 18 | 19 | int main() { 20 | // 입력 21 | cin >> N >> K; 22 | for (int i = 1; i <= N; i++) cin >> A[i] >> B[i]; 23 | 24 | // (a, b)쌍을 완전 탐색 25 | int Answer = 0; 26 | for (int a = 1; a <= 100; a++) { 27 | for (int b = 1; b <= 100; b++) { 28 | int Score = GetScore(a, b); 29 | Answer = max(Answer, Score); 30 | } 31 | } 32 | 33 | // 출력 34 | cout << Answer << endl; 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /codes/cpp/chap09/code_9-01.cpp: -------------------------------------------------------------------------------- 1 | // 변수 kakutei[i]는 노드 i의 최단 거리가 결정되었는지 아닌지를 나타낸다 2 | for (int i = 1; i <= N; i++) kakutei[i] = false; 3 | for (int i = 1; i <= N; i++) cur[i] = 2000000000; 4 | 5 | // 최단 거리를 업데이트해 나간다 6 | cur[1] = 0; 7 | while (true) { 8 | // [조작 A] 다음으로 확정할 노드 pos를 구한다 9 | int pos = -1; 10 | int MinDist = 2000000000; 11 | for (int i = 1; i <= N; i++) { 12 | if (kakutei[i] == true || MinDist <= cur[i]) continue; 13 | pos = i; 14 | MinDist = cur[i]; 15 | } 16 | if (pos == -1) break; // 다음으로 확정할 노드가 없는 경우, 조작 종료 17 | 18 | // [조작 B] pos와 인접한 노드의 cur 값을 업데이트 19 | kakutei[pos] = true; 20 | for (int i = 0; i < G[pos].size(); i++) { 21 | int nex = G[pos][i].first; // 인접한 노드의 번호 22 | int cost = G[pos][i].second; // 인접한 노드까지의 길이 23 | cur[nex] = min(cur[nex], cur[pos] + cost); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /codes/python/chap04/answer_A17.py: -------------------------------------------------------------------------------- 1 | # 입력(A, B 가 0 번부터 시작한다는 점에 유의) 2 | N = int(input()) 3 | A = list(map(int, input().split())) 4 | B = list(map(int, input().split())) 5 | 6 | # 동적 계획 알고리즘 7 | dp = [ None ] * (N+1) 8 | dp[1] = 0 9 | dp[2] = A[0] 10 | for i in range(3, N+1): 11 | dp[i] = min(dp[i-1]+A[i-2], dp[i-2]+B[i-3]) 12 | 13 | # 답의 복원 14 | # 변수 Place는 현재 위치(목표부터 진행한다) 15 | # 예를 들어, 입력 예의 경우 Place는 5 → 4 → 2 → 1로 변화한다 16 | Answer = [] 17 | Place = N 18 | while True: 19 | Answer.append(Place) 20 | if Place == 1: 21 | break 22 | 23 | # 어디에서 방 Place로 이동하는 것이 최적인지 구한다 24 | if dp[Place-1] + A[Place-2] == dp[Place]: 25 | Place = Place - 1 26 | else: 27 | Place = Place - 2 28 | Answer.reverse() 29 | 30 | # 답을 출력 31 | Answer2 = [str(i) for i in Answer] 32 | print(len(Answer)) 33 | print(" ".join(Answer2)) 34 | -------------------------------------------------------------------------------- /editorial/chap06/python/answer_B42.py: -------------------------------------------------------------------------------- 1 | # omote=1일 때 앞면의 합계가 양수, ura=1일 때 뒤쪽의 합계가 양수 2 | # omote=2일 때 앞면의 합계가 음수, ura=2일 때 뒤쪽의 합계가 음수 3 | def solve(omote, ura, A, B): 4 | sum = 0 5 | for i in range(N): 6 | card1 = A[i] 7 | if omote == 2: 8 | card1 = -A[i] 9 | card2 = B[i] 10 | if ura == 2: 11 | card2 = -B[i] 12 | # 카드 i를 선택해야 할까? 13 | if card1 + card2 >= 0: 14 | sum += (card1 + card2) 15 | return sum 16 | 17 | # 입력 18 | N = int(input()) 19 | A = [ None ] * N 20 | B = [ None ] * N 21 | for i in range(N): 22 | A[i], B[i] = map(int, input().split()) 23 | 24 | # 앞의 총합의 양과 음, 뒤의 총합의 양과 음을 완벽 탐색 25 | Answer1 = solve(1, 1, A, B); 26 | Answer2 = solve(1, 2, A, B); 27 | Answer3 = solve(2, 1, A, B); 28 | Answer4 = solve(2, 2, A, B); 29 | 30 | # 출력 31 | print(max(Answer1, Answer2, Answer3, Answer4)) 32 | -------------------------------------------------------------------------------- /codes/cpp/chap04/answer_A19.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | long long N, W, w[109], v[109]; 6 | long long dp[109][100009]; 7 | 8 | int main() { 9 | // 입력, 배열 초기화 10 | cin >> N >> W; 11 | for (int i = 1; i <= N; i++) cin >> w[i] >> v[i]; 12 | for (int i = 0; i <= N; i++) { 13 | for (int j = 0; j <= W; j++) dp[i][j] = -1'000'000'000'000'000LL; 14 | } 15 | 16 | // 동적 계획 알고리즘 17 | dp[0][0] = 0; 18 | for (int i = 1; i <= N; i++) { 19 | for (int j = 0; j <= W; j++) { 20 | if (j < w[i]) dp[i][j] = dp[i - 1][j]; 21 | else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i]); 22 | } 23 | } 24 | 25 | // 답 출력 26 | long long Answer = 0; 27 | for (int i = 0; i <= W; i++) Answer = max(Answer, dp[N][i]); 28 | cout << Answer << endl; 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /codes/java/chap03/answer_A11.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | N = sc.nextInt(); 9 | X = sc.nextInt(); 10 | A = new int[N + 1]; 11 | for (int i = 1; i <= N; i++) A[i] = sc.nextInt(); 12 | 13 | // 바이너리 서치를 수행한다 14 | int Answer = search(X); 15 | System.out.println(Answer); 16 | } 17 | 18 | static int N, X; 19 | static int[] A; 20 | 21 | // 정수 x가 몇 번째에 위치하는지 반환한다 22 | static int search(int x) { 23 | int L = 1, R = N; 24 | while (L <= R) { // 탐색 범위가 없어질 때까지 계속 비교한다 25 | int M = (L + R) / 2; 26 | if (x < A[M]) R = M - 1; 27 | if (x == A[M]) return M; 28 | if (x > A[M]) L = M + 1; 29 | } 30 | return -1; // 정수 x가 존재하지 않는다(주: 이 문제의 조건에서 -1이 반환되는 일은 없다) 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /codes/cpp/chap06/answer_A39.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int N, L[300009], R[300009]; 7 | vector> tmp; // 영화를 정렬하기 위한 임시 변수 8 | 9 | int main() { 10 | // 입력 11 | cin >> N; 12 | for (int i = 1; i <= N; i++) { 13 | cin >> L[i] >> R[i]; 14 | tmp.push_back(make_pair(R[i], L[i])); 15 | } 16 | 17 | // R의 오름차순으로 정렬 18 | sort(tmp.begin(), tmp.end()); 19 | for (int i = 1; i <= N; i++) { 20 | R[i] = tmp[i - 1].first; 21 | L[i] = tmp[i - 1].second; 22 | } 23 | 24 | // 종료 시각이 빠른 것부터 탐욕적으로 취해 간다(CurrentTime은 현재 시각) 25 | int CurrentTime = 0, Answer = 0; 26 | for (int i = 1; i <= N; i++) { 27 | if (CurrentTime <= L[i]) { 28 | CurrentTime = R[i]; 29 | Answer += 1; 30 | } 31 | } 32 | cout << Answer << endl; 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /codes/java/chap03/answer_A13.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int K = sc.nextInt(); 10 | int[] A = new int[N + 1]; 11 | for (int i = 1; i <= N; i++) A[i] = sc.nextInt(); 12 | 13 | // 배열 R의 정의 14 | int[] R = new int[N + 1]; 15 | 16 | // 자벌레 알고리즘 17 | for (int i = 1; i <= N - 1; i++) { 18 | // 시작 지점을 결정한다 19 | if (i == 1) R[i] = 1; 20 | else R[i] = R[i - 1]; 21 | 22 | // 한계까지 더해간다 23 | while (R[i] < N && A[R[i] + 1] - A[i] <= K) { 24 | R[i] += 1; 25 | } 26 | } 27 | 28 | // 출력(답은 최대 50억 정도가 되므로 long형을 사용해야 한다.) 29 | long Answer = 0; 30 | for (int i = 1; i <= N - 1; i++) Answer += (R[i] - i); 31 | System.out.println(Answer); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /editorial/chap06/cpp/answer_B39.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, D; 5 | int X[2009], Y[2009]; 6 | bool used[2009]; // used[i]는 작업 i를 선택했는지 여부를 나타냅니다. 7 | int Answer = 0; 8 | 9 | int main() { 10 | // 입력 11 | cin >> N >> D; 12 | for (int i = 1; i <= N; i++) cin >> X[i] >> Y[i]; 13 | 14 | // 답을 구한다 15 | for (int i = 1; i <= D; i++) { 16 | int maxValue = 0; // 급여의 최대치 17 | int maxID = -1; // 월급이 최대가 되는 직업의 수 18 | for (int j = 1; j <= N; j++) { 19 | if (used[j] == true) continue; 20 | if (maxValue < Y[j] && X[j] <= i) { 21 | maxValue = Y[j]; 22 | maxID = j; 23 | } 24 | } 25 | 26 | // 선택할 수 있는 직업이 있는 경우 27 | if (maxID != -1) { 28 | Answer += maxValue; 29 | used[maxID] = true; 30 | } 31 | } 32 | 33 | // 출력 34 | cout << Answer << endl; 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /editorial/chap08/cpp/answer_B57.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, K; 6 | int dp[32][300009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N >> K; 11 | 12 | // 1 회 조작 후 값 구하기 13 | for (int i = 1; i <= N; i++) { 14 | string str = to_string(i); 15 | dp[0][i] = i; 16 | for (int j = 0; j < str.size(); j++) { 17 | dp[0][i] -= (int)(str[j] - '0'); 18 | } 19 | } 20 | 21 | // 사전 계산 22 | for (int d = 1; d <= 29; d++) { 23 | for (int i = 1; i <= N; i++) dp[d][i] = dp[d - 1][dp[d - 1][i]]; 24 | } 25 | 26 | // 답을 구한다 27 | for (int i = 1; i <= N; i++) { 28 | int CurrentNum = i; // 현재 정수 29 | for (int d = 29; d >= 0; d--) { 30 | if ((K / (1 << d)) % 2 != 0) CurrentNum = dp[d][CurrentNum]; 31 | } 32 | cout << CurrentNum << endl; 33 | } 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /codes/cpp/chap08/answer_A60.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, A[200009]; 6 | int Answer[200009]; 7 | stack> Level2; 8 | 9 | int main() { 10 | // 입력 11 | cin >> N; 12 | for (int i = 1; i <= N; i++) cin >> A[i]; 13 | 14 | // 스택 변화 재현 15 | for (int i = 1; i <= N; i++) { 16 | if (i >= 2) { 17 | Level2.push(make_pair(i - 1, A[i - 1])); 18 | while (!Level2.empty()) { 19 | int kabuka = Level2.top().second; 20 | if (kabuka <= A[i]) Level2.pop(); 21 | else break; 22 | } 23 | } 24 | 25 | // 기산일 특정 26 | if (!Level2.empty()) Answer[i] = Level2.top().first; 27 | else Answer[i] = -1; 28 | } 29 | 30 | // 출력 31 | for (int i = 1; i <= N; i++) { 32 | if (i >= 2) cout << " "; 33 | cout << Answer[i]; 34 | } 35 | cout << endl; 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /codes/java/chap02/answer_A07.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int D = sc.nextInt(); 9 | int N = sc.nextInt(); 10 | int[] B = new int[D + 2]; 11 | int[] L = new int[N + 1]; 12 | int[] R = new int[N + 1]; 13 | for (int i = 1; i <= N; i++) { 14 | L[i] = sc.nextInt(); 15 | R[i] = sc.nextInt(); 16 | } 17 | 18 | // 전일 비에 더한다 19 | for (int d = 1; d <= D; d++) B[d] = 0; 20 | for (int i = 1; i <= N; i++) { 21 | B[L[i]] += 1; 22 | B[R[i] + 1] -= 1; 23 | } 24 | 25 | // 누적 합을 구한다 → 출력 26 | int[] Answer = new int[D + 2]; 27 | Answer[0] = 0; 28 | for (int d = 1; d <= D; d++) Answer[d] = Answer[d - 1] + B[d]; 29 | for (int d = 1; d <= D; d++) System.out.println(Answer[d]); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /codes/python/chap10/answer_A76.py: -------------------------------------------------------------------------------- 1 | import bisect 2 | 3 | # 입력 4 | N, W, L, R = map(int, input().split()) 5 | X = list(map(int, input().split())) 6 | 7 | # 서쪽 끝을 징검다리 0, 동쪽 끝을 징검다리 N+1로 간주한다 8 | X = [ 0 ] + X + [ W ] 9 | 10 | # 동적 계획 알고리즘(책에서 sum[i]은 본 코드의 dpsum[i]에 해당) 11 | MOD = 10 ** 9 + 7 # = 1000000007 12 | dp = [ 0 ] * (N + 2) 13 | dpsum = [ 0 ] * (N + 2) 14 | dp[0] = 1 15 | dpsum[0] = 1 16 | for i in range(1, N + 2): 17 | posl = bisect.bisect_left(X, X[i] - R) 18 | posr = bisect.bisect_left(X, X[i] - L + 1) - 1 19 | # dp[i]의 값을 누적합으로 계산(C++와 달리 (음수)% MOD도 0 이상 MOD-1 이하가 된다는 점에 유의) 20 | dp[i] = (dpsum[posr] if posr >= 0 else 0) - (dpsum[posl - 1] if posl >= 1 else 0) 21 | dp[i] %= MOD 22 | # 누적합 dpsum[i]의 값을 갱신한다. 23 | dpsum[i] = dpsum[i - 1] + dp[i] 24 | dpsum[i] %= MOD 25 | 26 | # 출력 27 | print(dp[N + 1]) -------------------------------------------------------------------------------- /codes/cpp/chap04/answer_A18.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, S, A[69]; 5 | bool dp[69][10009]; 6 | 7 | int main() { 8 | // 입력 9 | cin >> N >> S; 10 | for (int i = 1; i <= N; i++) cin >> A[i]; 11 | 12 | // 동적 계획 알고리즘 (i = 0) 13 | dp[0][0] = true; 14 | for (int i = 1; i <= S; i++) dp[0][i] = false; 15 | 16 | // 동적 계획 알고리즘 (i >= 1) 17 | for (int i = 1; i <= N; i++) { 18 | for (int j = 0; j <= S; j++) { 19 | if (j < A[i]) { 20 | if (dp[i - 1][j] == true) dp[i][j] = true; 21 | else dp[i][j] = false; 22 | } 23 | if (j >= A[i]) { 24 | if (dp[i - 1][j] == true || dp[i - 1][j - A[i]] == true) dp[i][j] = true; 25 | else dp[i][j] = false; 26 | } 27 | } 28 | } 29 | 30 | // 출력 31 | if (dp[N][S] == true) cout << "Yes" << endl; 32 | else cout << "No" << endl; 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /codes/cpp/chap09/answer_A65_DFS.cpp: -------------------------------------------------------------------------------- 1 | // ############################### 2 | // # 깊이 우선 탐색을 이용한 구현 3 | // ############################### 4 | 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | int N, A[100009], dp[100009]; 10 | vector G[100009]; 11 | 12 | void dfs(int pos) { 13 | // 재귀적으로 계산하기 14 | for (int i = 0; i < G[pos].size(); i++) { 15 | int to = G[pos][i]; // to는 직속 부하 직원의 번호 16 | dfs(to); 17 | dp[pos] += (dp[to] + 1); 18 | } 19 | } 20 | 21 | int main() { 22 | // 입력 23 | cin >> N; 24 | for (int i = 2; i <= N; i++) { 25 | cin >> A[i]; 26 | G[A[i]].push_back(i); // '상사→부하' 방향으로 에지를 추가 27 | } 28 | 29 | // 깊이 우선 탐색 30 | dfs(1); 31 | 32 | // 공백으로 구분해서 출력 33 | for (int i = 1; i <= N; i++) { 34 | if (i >= 2) cout << " "; 35 | cout << dp[i]; 36 | } 37 | cout << endl; 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /codes/java/chap04/answer_A25.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력(배열 c는 0번부터 시작한다는 점에 유의하세요!) 8 | int H = sc.nextInt(); 9 | int W = sc.nextInt(); 10 | String[] c = new String[H]; 11 | for (int i = 0; i < H; i++) c[i] = sc.next(); 12 | 13 | // 동적 계획 알고리즘 14 | long[][] dp = new long[H][W]; 15 | for (int i = 0; i < H; i++) { 16 | for (int j = 0; j < W; j++) { 17 | if (i == 0 && j == 0) { 18 | dp[i][j] = 1; 19 | } 20 | else { 21 | dp[i][j] = 0; 22 | if (i >= 1 && c[i - 1].charAt(j) == '.') dp[i][j] += dp[i - 1][j]; 23 | if (j >= 1 && c[i].charAt(j - 1) == '.') dp[i][j] += dp[i][j - 1]; 24 | } 25 | } 26 | } 27 | 28 | // 출력 29 | System.out.println(dp[H-1][W-1]); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /editorial/chap02/python/answer_B06.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | A = list(map(int, input().split())) 4 | Q = int(input()) 5 | L = [ None ] * Q 6 | R = [ None ] * Q 7 | for i in range(Q): 8 | L[i], R[i] = map(int, input().split()) 9 | 10 | # 일치하는 개수와 불일치하는 개수의 누적합을 구한다. 11 | # 배열 A 가 0 번부터 시작한다는 점에 주의! 12 | Atari = [ 0 ] * (N + 1) 13 | Hazre = [ 0 ] * (N + 1) 14 | for i in range(1, N+1): 15 | # Atari에 대한 계산 16 | Atari[i] = Atari[i - 1] 17 | if A[i - 1] == 1: 18 | Atari[i] += 1 19 | # Hazre에 대해 계산 20 | Hazre[i] = Hazre[i - 1] 21 | if A[i - 1] == 0: 22 | Hazre[i] += 1 23 | 24 | # 질문에 답한다 25 | for i in range(Q): 26 | NumAtari = Atari[R[i]] - Atari[L[i] - 1] 27 | NumHazre = Hazre[R[i]] - Hazre[L[i] - 1] 28 | if NumAtari > NumHazre: 29 | print("win") 30 | elif NumAtari == NumHazre: 31 | print("draw") 32 | else: 33 | print("lose") 34 | -------------------------------------------------------------------------------- /codes/cpp/chap04/answer_A20.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int N, M, dp[2009][2009]; 7 | string S, T; 8 | 9 | int main() { 10 | // 입력 11 | cin >> S; N = S.size(); 12 | cin >> T; M = T.size(); 13 | 14 | // 동적 계획 알고리즘 15 | dp[0][0] = 0; 16 | for (int i = 0; i <= N; i++) { 17 | for (int j = 0; j <= M; j++) { 18 | if (i >= 1 && j >= 1 && S[i - 1] == T[j - 1]) { 19 | dp[i][j] = max({ dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1] + 1 }); 20 | } 21 | else if (i >= 1 && j >= 1) { 22 | dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); 23 | } 24 | else if (i >= 1) { 25 | dp[i][j] = dp[i - 1][j]; 26 | } 27 | else if (j >= 1) { 28 | dp[i][j] = dp[i][j - 1]; 29 | } 30 | } 31 | } 32 | 33 | // 출력 34 | cout << dp[N][M] << endl; 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /editorial/chap04/cpp/answer_B19.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | long long N, W, w[109], v[109]; 6 | long long dp[109][100009]; 7 | 8 | int main() { 9 | // 입력, 배열 초기화 10 | cin >> N >> W; 11 | for (int i = 1; i <= N; i++) cin >> w[i] >> v[i]; 12 | for (int i = 0; i <= N; i++) { 13 | for (int j = 0; j <= 100000; j++) dp[i][j] = 1'000'000'000'000'000LL; 14 | } 15 | 16 | // 동적 계획 알고리즘 17 | dp[0][0] = 0; 18 | for (int i = 1; i <= N; i++) { 19 | for (int j = 0; j <= 100000; j++) { 20 | if (j < v[i]) dp[i][j] = dp[i - 1][j]; 21 | else dp[i][j] = min(dp[i - 1][j], dp[i - 1][j - v[i]] + w[i]); 22 | } 23 | } 24 | 25 | // 답 출력 26 | long long Answer = 0; 27 | for (int i = 0; i <= 100000; i++) { 28 | if (dp[N][i] <= W) Answer = i; 29 | } 30 | cout << Answer << endl; 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /editorial/chap09/python/answer_B63.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | H, W = map(int, input().split()) 3 | sx, sy = map(int, input().split()) 4 | sx -= 1 5 | sy -= 1 6 | gx, gy = map(int, input().split()) 7 | gx -= 1 8 | gy -= 1 9 | S = [input() for _ in range(H)] 10 | 11 | INF = 1 << 61 12 | # 파이썬에서는 다차원 배열을 1차원으로 평평하게 만드는 것이 더 빠르다(여기서는 사용하지 않는다). 13 | cost = [[INF] * W for _ in range(H)] 14 | 15 | q = [] # queue는 list로 재현할 수 있다 16 | # 정점에 방문하는 부분을 함수로 잘라내면 좋다 17 | def push(x: int, y: int, c: int): 18 | if S[x][y] == '#': 19 | return 20 | if cost[x][y] <= c: 21 | return 22 | cost[x][y] = c 23 | q.append((x, y)) 24 | 25 | # 너비 우선 탐색 26 | push(sx, sy, 0) 27 | for x, y in q: 28 | c2 = cost[x][y] + 1 29 | push(x - 1, y, c2) 30 | push(x, y - 1, c2) 31 | push(x + 1, y, c2) 32 | push(x, y + 1, c2) 33 | 34 | print(cost[gx][gy]) 35 | -------------------------------------------------------------------------------- /codes/java/chap08/answer_A55.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | // 입력 6 | Scanner sc = new Scanner(System.in); 7 | int Q = sc.nextInt(); 8 | int[] queryType = new int[Q + 1]; 9 | int[] x = new int[Q + 1]; 10 | for (int i = 1; i <= Q; i++) { 11 | queryType[i] = sc.nextInt(); 12 | x[i] = sc.nextInt(); 13 | } 14 | 15 | // 쿼리 처리 16 | TreeSet S = new TreeSet<>(); 17 | for (int i = 1; i <= Q; i++) { 18 | if (queryType[i] == 1) { 19 | S.add(x[i]); 20 | } 21 | if (queryType[i] == 2) { 22 | S.remove(x[i]); 23 | } 24 | if (queryType[i] == 3) { 25 | Integer res = S.higher(x[i] - 1); // higher 함수는 '인수보다 큰 것 중 가장 작은 요소'를 반환하므로 인수를 x[i] - 1로 설정 26 | System.out.println(res != null ? res : -1); 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /codes/cpp/chap09/answer_A67.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | // Union-Find 클래스의 구현은 9.6절 참조 7 | int N, M; 8 | int A[100009], B[100009], C[100009]; 9 | UnionFind UF; 10 | 11 | int main() { 12 | // 입력 13 | cin >> N >> M; 14 | for (int i = 1; i <= M; i++) cin >> A[i] >> B[i] >> C[i]; 15 | 16 | // 에지를 길이의 오름차순으로 정렬한다 17 | vector> EdgeList; 18 | for (int i = 1; i <= M; i++) EdgeList.push_back(make_pair(C[i], i)); 19 | sort(EdgeList.begin(), EdgeList.end()); 20 | 21 | // 최소 전역 트리를 구한다 22 | int Answer = 0; UF.init(N); 23 | for (int i = 0; i < EdgeList.size(); i++) { 24 | int idx = EdgeList[i].second; 25 | if (UF.same(A[idx], B[idx]) == false) { 26 | UF.unite(A[idx], B[idx]); 27 | Answer += C[idx]; 28 | } 29 | } 30 | cout << Answer << endl; 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /editorial/chap05/answer_B30.py: -------------------------------------------------------------------------------- 1 | # a의 b제곱을 m으로 나눈 나머지를 반환하는 함수 2 | def Power(a, b, m): 3 | p = a 4 | Answer = 1 5 | for i in range(30): 6 | wari = 2 ** i 7 | if (b // wari) % 2 == 1: 8 | Answer = (Answer * p) % m # a의 2^i 제곱을 곱할 때 9 | p = (p * p) % m 10 | return Answer 11 | 12 | # a÷b를 m으로 나눈 나머지를 반환하는 함수 13 | def Division(a, b, m): 14 | return (a * Power(b, m - 2, m)) % m 15 | 16 | # nCr mod 1000000007을 반환하는 함수 17 | def ncr(n, r): 18 | M = 1000000007; 19 | 20 | # 순서 1: 분자 a를 구한다 21 | a = 1; 22 | for i in range(1, n+1): 23 | a = (a*i) % M 24 | 25 | # 순서 2: 분모 b를 구한다 26 | b = 1; 27 | for i in range(1, r+1): 28 | b = (b * i) % M 29 | for i in range(1, n-r+1): 30 | b = (b * i) % M 31 | 32 | # 순서 3: 답을 구한다 33 | return Division(a, b, M); 34 | 35 | # 입력 36 | H, W = map(int, input().split()) 37 | 38 | # 출력 39 | print(ncr(H + W - 2, W - 1)) 40 | -------------------------------------------------------------------------------- /codes/java/chap06/answer_A38.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int D = sc.nextInt(); 9 | int N = sc.nextInt(); 10 | int[] L = new int[N + 1]; 11 | int[] R = new int[N + 1]; 12 | int[] H = new int[N + 1]; 13 | for (int i = 1; i <= N; i++) { 14 | L[i] = sc.nextInt(); 15 | R[i] = sc.nextInt(); 16 | H[i] = sc.nextInt(); 17 | } 18 | 19 | // 배열 초기화(1일은 24시간) 20 | int[] LIM = new int[D + 1]; 21 | for (int i = 1; i <= D; i++) LIM[i] = 24; 22 | 23 | // 상한 값을 구한다 24 | for (int i = 1; i <= N; i++) { 25 | for (int j = L[i]; j <= R[i]; j++) LIM[j] = Math.min(LIM[j], H[i]); 26 | } 27 | 28 | // 출력 29 | int Answer = 0; 30 | for (int i = 1; i <= D; i++) Answer += LIM[i]; 31 | System.out.println(Answer); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /codes/java/chap04/answer_A24.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int[] A = new int[N + 1]; 10 | for (int i = 1; i <= N; i++) A[i] = sc.nextInt(); 11 | 12 | // 배열 등의 정의 13 | int LEN = 0; // LEN은 L의 길이(예: L[4]까지 쓰여 있는 경우 LEN=4) 14 | ArrayList L = new ArrayList(); 15 | 16 | // 동적 계획 알고리즘(배열 dp를 사용하지 않는 구현) 17 | for (int i = 1; i <= N; i++) { 18 | int pos = ~Collections.binarySearch(L, A[i], (x, y) -> x.compareTo(y) >= 0 ? 1 : -1); 19 | 20 | // L의 최대 값보다 A[i]가 더 큰 경우 21 | if (pos >= LEN) { 22 | LEN += 1; 23 | L.add(A[i]); 24 | } 25 | // 그렇지 않은 경우 26 | else { 27 | L.set(pos, A[i]); 28 | } 29 | } 30 | 31 | // 답을 출력 32 | System.out.println(LEN); 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /codes/python/chap02/answer_A08.py: -------------------------------------------------------------------------------- 1 | # 입력(전반부) 2 | H, W = map(int, input().split()) 3 | X = [ None ] * (H) 4 | Z = [ [ 0 ] * (W + 1) for i in range(H + 1) ] 5 | for i in range(H): 6 | X[i] = list(map(int, input().split())) 7 | 8 | # 입력(후반부) 9 | Q = int(input()) 10 | A = [ None ] * Q 11 | B = [ None ] * Q 12 | C = [ None ] * Q 13 | D = [ None ] * Q 14 | for i in range(Q): 15 | A[i], B[i], C[i], D[i] = map(int, input().split()) 16 | 17 | # 배열 Z는 이미 초기화됨 18 | # 가로 방향으로 누적 합을 구한다 19 | # X[i-1][j-1] 등으로 되어 있는 것은 배열이 0번부터 시작되기 때문입니다 20 | for i in range(1, H+1): 21 | for j in range(1, W+1): 22 | Z[i][j] = Z[i][j-1] + X[i-1][j-1] 23 | 24 | # 세로 방향으로 누적 합을 구한다 25 | for j in range(1, W+1): 26 | for i in range(1, H+1): 27 | Z[i][j] = Z[i-1][j] + Z[i][j] 28 | 29 | # 답을 구한다 30 | for i in range(Q): 31 | print(Z[C[i]][D[i]] + Z[A[i]-1][B[i]-1] - Z[A[i]-1][D[i]] - Z[C[i]][B[i]-1]) 32 | -------------------------------------------------------------------------------- /editorial/chap04/cpp/answer_B21.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N; 6 | int dp[1009][1009]; 7 | string S; 8 | 9 | int main() { 10 | // 입력 11 | cin >> N; 12 | cin >> S; 13 | 14 | // 동적 계획 알고리즘(초기 상태) 15 | for (int i = 0; i < N; i++) dp[i][i] = 1; 16 | for (int i = 0; i < N - 1; i++) { 17 | if (S[i] == S[i + 1]) dp[i][i + 1] = 2; 18 | else dp[i][i + 1] = 1; 19 | } 20 | 21 | // 동적 계획 알고리즘(상태 전환) 22 | for (int LEN = 2; LEN <= N - 1; LEN++) { 23 | for (int l = 0; l < N - LEN; l++) { 24 | int r = l + LEN; 25 | 26 | if (S[l] == S[r]) { 27 | dp[l][r] = max({ dp[l][r - 1], dp[l + 1][r], dp[l + 1][r - 1] + 2 }); 28 | } 29 | else { 30 | dp[l][r] = max({ dp[l][r - 1], dp[l + 1][r] }); 31 | } 32 | } 33 | } 34 | 35 | // 답을 구한다 36 | cout << dp[0][N - 1] << endl; 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /editorial/chap05/python/answer_B30.py: -------------------------------------------------------------------------------- 1 | # a의 b제곱을 m으로 나눈 나머지를 반환하는 함수 2 | def Power(a, b, m): 3 | p = a 4 | Answer = 1 5 | for i in range(30): 6 | wari = 2 ** i 7 | if (b // wari) % 2 == 1: 8 | Answer = (Answer * p) % m # a의 2^i 제곱을 곱할 때 9 | p = (p * p) % m 10 | return Answer 11 | 12 | # a÷b를 m으로 나눈 나머지를 반환하는 함수 13 | def Division(a, b, m): 14 | return (a * Power(b, m - 2, m)) % m 15 | 16 | # nCr mod 1000000007을 반환하는 함수 17 | def ncr(n, r): 18 | M = 1000000007; 19 | 20 | # 순서 1: 분자 a를 구한다 21 | a = 1; 22 | for i in range(1, n+1): 23 | a = (a*i) % M 24 | 25 | # 순서 2: 분모 b를 구한다 26 | b = 1; 27 | for i in range(1, r+1): 28 | b = (b * i) % M 29 | for i in range(1, n-r+1): 30 | b = (b * i) % M 31 | 32 | # 순서 3: 답을 구한다 33 | return Division(a, b, M); 34 | 35 | # 입력 36 | H, W = map(int, input().split()) 37 | 38 | # 출력 39 | print(ncr(H + W - 2, W - 1)) 40 | -------------------------------------------------------------------------------- /editorial/chap06/cpp/answer_B38.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int N, ret1[1 << 18], ret2[1 << 18]; 7 | string S; 8 | 9 | int main() { 10 | // 입력 11 | cin >> N >> S; 12 | 13 | // 답을 구한다 14 | int streak1 = 1; ret1[0] = 1; // streak1은 'A가 몇 개 연속으로 이어졌는가' + 1 15 | for (int i = 0; i < N - 1; i++) { 16 | if (S[i] == 'A') streak1 += 1; 17 | if (S[i] == 'B') streak1 = 1; 18 | ret1[i + 1] = streak1; 19 | } 20 | int streak2 = 1; ret2[N - 1] = 1; // streak2는 'B가 몇 개 연속으로 이어졌는가' + 1 21 | for (int i = N - 2; i >= 0; i--) { 22 | if (S[i] == 'B') streak2 += 1; 23 | if (S[i] == 'A') streak2 = 1; 24 | ret2[i] = streak2; 25 | } 26 | 27 | // 출력 28 | long long Answer = 0; 29 | for (int i = 0; i < N; i++) Answer += max(ret1[i], ret2[i]); 30 | cout << Answer << endl; 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /codes/java/chap08/answer_A54.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | // 입력 6 | Scanner sc = new Scanner(System.in); 7 | int Q = sc.nextInt(); 8 | int[] queryType = new int[Q + 1]; 9 | String[] x = new String[Q + 1]; 10 | int[] y = new int[Q + 1]; 11 | for (int i = 1; i <= Q; i++) { 12 | queryType[i] = sc.nextInt(); 13 | if (queryType[i] == 1) { 14 | x[i] = sc.next(); 15 | y[i] = sc.nextInt(); 16 | } 17 | if (queryType[i] == 2) { 18 | x[i] = sc.next(); 19 | } 20 | } 21 | 22 | // 쿼리 처리 23 | Map scoreMap = new HashMap<>(); 24 | for (int i = 1; i <= Q; i++) { 25 | if (queryType[i] == 1) { 26 | scoreMap.put(x[i], y[i]); 27 | } 28 | if (queryType[i] == 2) { 29 | System.out.println(scoreMap.get(x[i])); 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /editorial/chap03/cpp/answer_B13.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | long long N, K; 5 | long long A[100009]; 6 | long long S[100009]; // 누적 합계 7 | long long R[100009]; // 왼쪽 끝이 정해지면 오른쪽 끝은 어디까지 갈 수 있을까 8 | 9 | // A[l]에서 A[r]까지의 합계값 10 | long long sum(int l, int r) { 11 | return S[r] - S[l - 1]; 12 | } 13 | 14 | int main() { 15 | // 입력 16 | cin >> N >> K; 17 | for (int i = 1; i <= N; i++) cin >> A[i]; 18 | 19 | // 누적 합을 구한다 20 | S[0] = 0; 21 | for (int i = 1; i <= N; i++) S[i] = S[i - 1] + A[i]; 22 | 23 | // 자벌레 알고리즘 24 | for (int i = 1; i <= N; i++) { 25 | if (i == 1) R[i] = 0; 26 | else R[i] = R[i - 1]; 27 | while (R[i] < N && sum(i, R[i] + 1) <= K) { 28 | R[i] += 1; 29 | } 30 | } 31 | 32 | // 답을 구한다 33 | long long Answer = 0; 34 | for (int i = 1; i <= N; i++) Answer += (R[i] - i + 1); 35 | cout << Answer << endl; 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /editorial/chap02/python/answer_B08.py: -------------------------------------------------------------------------------- 1 | # 입력(전반부) 2 | N = int(input()) 3 | X = [ None ] * N 4 | Y = [ None ] * N 5 | for i in range(N): 6 | X[i], Y[i] = map(int, input().split()) 7 | 8 | # 입력(후반부) 9 | Q = int(input()) 10 | A = [ None ] * Q 11 | B = [ None ] * Q 12 | C = [ None ] * Q 13 | D = [ None ] * Q 14 | for i in range(Q): 15 | A[i], B[i], C[i], D[i] = map(int, input().split()) 16 | 17 | # 각 좌표에 있는 점의 개수를 세어본다 18 | S = [ [ 0 ] * 1501 for i in range(1501) ] 19 | for i in range(N): 20 | S[X[i]][Y[i]] += 1 21 | 22 | # 누적 합을 구한다 23 | T = [ [ 0 ] * 1501 for i in range(1501) ] 24 | for i in range(1, 1501): 25 | for j in range(1, 1501): 26 | T[i][j] = T[i][j-1] + S[i][j] 27 | for j in range(1, 1501): 28 | for i in range(1, 1501): 29 | T[i][j] = T[i-1][j] + T[i][j] 30 | 31 | # 답을 구한다 32 | for i in range(Q): 33 | print(T[C[i]][D[i]] + T[A[i] - 1][B[i] - 1] - T[A[i] - 1][D[i]] - T[C[i]][B[i] - 1]) 34 | -------------------------------------------------------------------------------- /codes/python/chap02/answer_A09.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | H, W, N = map(int, input().split()) 3 | A = [ None ] * N 4 | B = [ None ] * N 5 | C = [ None ] * N 6 | D = [ None ] * N 7 | X = [ None ] * (W) 8 | for t in range(N): 9 | A[t], B[t], C[t], D[t] = map(int, input().split()) 10 | 11 | # 각 날짜에 대해 더한다 12 | X = [ [ 0 ] * (W + 2) for i in range(H + 2) ] 13 | Z = [ [ 0 ] * (W + 2) for i in range(H + 2) ] 14 | for t in range(N): 15 | X[A[t]][B[t]] += 1 16 | X[A[t]][D[t]+1] -= 1 17 | X[C[t]+1][B[t]] -= 1 18 | X[C[t]+1][D[t]+1] += 1 19 | 20 | # 2차원 누적 합을 구한다 21 | for i in range(1, H+1): 22 | for j in range(1, W+1): 23 | Z[i][j] = Z[i][j-1] + X[i][j] 24 | for j in range(1, W+1): 25 | for i in range(1, H+1): 26 | Z[i][j] = Z[i-1][j] + Z[i][j] 27 | 28 | # 출력 29 | for i in range(1, H+1): 30 | for j in range(1, W+1): 31 | if j >= 2: 32 | print(" ", end="") 33 | print(Z[i][j], end="") 34 | print("") 35 | -------------------------------------------------------------------------------- /editorial/chap04/cpp/answer_B20.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int N, M, dp[2009][2009]; 7 | string S, T; 8 | 9 | int main() { 10 | // 입력 11 | cin >> S; N = S.size(); 12 | cin >> T; M = T.size(); 13 | 14 | // 동적 계획 알고리즘 15 | dp[0][0] = 0; 16 | for (int i = 0; i <= N; i++) { 17 | for (int j = 0; j <= M; j++) { 18 | if (i >= 1 && j >= 1 && S[i - 1] == T[j - 1]) { 19 | dp[i][j] = min({ dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] }); 20 | } 21 | else if (i >= 1 && j >= 1) { 22 | dp[i][j] = min({ dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + 1 }); 23 | } 24 | else if (i >= 1) { 25 | dp[i][j] = dp[i - 1][j] + 1; 26 | } 27 | else if (j >= 1) { 28 | dp[i][j] = dp[i][j - 1] + 1; 29 | } 30 | } 31 | } 32 | 33 | // 출력 34 | cout << dp[N][M] << endl; 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /codes/cpp/chap09/answer_A63.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int N, M, A[100009], B[100009]; 7 | int dist[100009]; 8 | vector G[100009]; 9 | queue Q; 10 | 11 | int main() { 12 | // 입력 13 | cin >> N >> M; 14 | for (int i = 1; i <= M; i++) { 15 | cin >> A[i] >> B[i]; 16 | G[A[i]].push_back(B[i]); 17 | G[B[i]].push_back(A[i]); 18 | } 19 | 20 | // 너비 우선 탐색(dist[i]=?가 아니라 dist[i]=-1로 초기화하는 것에 주의) 21 | for (int i = 1; i <= N; i++) dist[i] = -1; 22 | Q.push(1); 23 | dist[1] = 0; 24 | while (!Q.empty()) { 25 | int pos = Q.front(); Q.pop(); 26 | for (int i = 0; i < G[pos].size(); i++) { 27 | int to = G[pos][i]; 28 | if (dist[to] == -1) { 29 | dist[to] = dist[pos] + 1; 30 | Q.push(to); 31 | } 32 | } 33 | } 34 | 35 | // 출력 36 | for (int i = 1; i <= N; i++) cout << dist[i] << endl; 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /codes/java/chap03/answer_A15.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int[] A = new int[N + 1]; 10 | for (int i = 1; i <= N; i++) A[i] = sc.nextInt(); 11 | 12 | // 배열 T 작성 및 중복 삭제 13 | HashSet tmp = new HashSet(); 14 | for (int i = 1; i <= N; i++) tmp.add(A[i]); 15 | ArrayList T = new ArrayList<>(tmp); 16 | Collections.sort(T); 17 | 18 | // 답을 구한다 19 | int[] B = new int[N + 1]; 20 | for (int i = 1; i <= N; i++) { 21 | B[i] = ~Collections.binarySearch(T, A[i], (x, y) -> x.compareTo(y) >= 0 ? 1 : -1); 22 | B[i] += 1; 23 | } 24 | 25 | // 답을 공백으로 구분해서 출력 26 | for (int i = 1; i <= N; i++) { 27 | if (i >= 2) System.out.print(" "); 28 | System.out.print(B[i]); 29 | } 30 | System.out.println(); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /codes/cpp/chap05/answer_A34.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, X, Y, A[100009]; 5 | int grundy[100009]; 6 | 7 | int main() { 8 | // [ 입력 ] 9 | cin >> N >> X >> Y; 10 | for (int i = 1; i <= N; i++) cin >> A[i]; 11 | 12 | // [ Grundy 수를 구한다 ] 13 | // 변수 grundy[i]: 돌이 i개일 때의 Grundy 수 14 | // 변수 Transit[i]: Grundy 수가 i가 되도록 전이할 수 있는가 15 | for (int i = 0; i <= 100000; i++) { 16 | bool Transit[3] = { false, false, false }; 17 | if (i >= X) Transit[grundy[i - X]] = true; 18 | if (i >= Y) Transit[grundy[i - Y]] = true; 19 | if (Transit[0] == false) grundy[i] = 0; 20 | else if (Transit[1] == false) grundy[i] = 1; 21 | else grundy[i] = 2; 22 | } 23 | 24 | // [ 출력 ] 25 | int XOR_Sum = 0; 26 | for (int i = 1; i <= N; i++) XOR_Sum = (XOR_Sum ^ grundy[A[i]]); 27 | if (XOR_Sum != 0) cout << "First" << endl; 28 | if (XOR_Sum == 0) cout << "Second" << endl; 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /codes/cpp/chap03/answer_A12.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | long long N, K; 5 | long long A[100009]; 6 | 7 | // 답이 x 이하인지 판정하고 Yes라면 true, No라면 false를 반환한다 8 | bool check(long long x) { 9 | long long sum = 0; 10 | for (int i = 1; i <= N; i++) sum += x / A[i]; //'x ÷ A[i]'의 소수점 이하를 버린다 11 | if (sum >= K) return true; 12 | return false; 13 | } 14 | 15 | int main() { 16 | // 입력 17 | cin >> N >> K; 18 | for (int i = 1; i <= N; i++) cin >> A[i]; 19 | 20 | // 바이너리 서치 21 | // Left는 탐색 범위의 왼쪽 끝, Right는 탐색 범위의 오른쪽 끝을 나타낸다 22 | long long Left = 1, Right = 1'000'000'000; 23 | while (Left < Right) { 24 | long long Mid = (Left + Right) / 2; 25 | bool Answer = check(Mid); 26 | if (Answer == false) Left = Mid + 1; // 답이 Mid+1 이상임을 알 수 있다 27 | if (Answer == true) Right = Mid; // 답이 Mid 이하임을 알 수 있다 28 | } 29 | 30 | // 출력(이때, Left=Right가 된다) 31 | cout << Left << endl; 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /codes/cpp/chap10/answer_A77.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, L, K, A[100009]; 5 | 6 | bool check(int x) { 7 | int Count = 0, Last_Kireme = 0;// Count는 현 시점에서 몇 번 잘랐는가를 나타낸다 8 | for (int i = 1; i <= N; i++) { 9 | if (A[i] - Last_Kireme >= x && L - A[i] >= x) { 10 | Count += 1; 11 | Last_Kireme = A[i]; 12 | } 13 | } 14 | if (Count >= K) return true; 15 | return false; 16 | } 17 | 18 | int main() { 19 | // 입력 20 | cin >> N >> L >> K; 21 | for (int i = 1; i <= N; i++) cin >> A[i]; 22 | 23 | // 바이너리 서치(left: 현재의 하한/ right: 현재의 상한) 24 | long long left = 1, right = 1'000'000'000; 25 | while (left < right) { 26 | long long mid = (left + right + 1) / 2; 27 | bool Answer = check(mid); 28 | if (Answer == false) right = mid - 1; // 답이 전반 부분으로 좁혀진다 29 | if (Answer == true) left = mid; // 답이 후반 부분으로 좁혀진다 30 | } 31 | 32 | // 출력 33 | cout << left << endl; 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /codes/cpp/chap03/answer_A15.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | // 입력 8 | int N, A[100009], B[100009]; 9 | cin >> N; 10 | for (int i = 1; i <= N; i++) cin >> A[i]; 11 | 12 | // 배열 T 작성 13 | vector T; 14 | for (int i = 1; i <= N; i++) T.push_back(A[i]); 15 | sort(T.begin(), T.end()); 16 | 17 | // 배열 T의 중복을 제거한다 18 | // erase 함수, unique 함수는 이 책의 범위를 벗어나지만, 꼭 확인해 두자 19 | T.erase(unique(T.begin(), T.end()), T.end()); 20 | 21 | // 답을 구한다 22 | for (int i = 1; i <= N; i++) { 23 | // vector 타입의 lower_bound는 다음과 같은 형식으로 작성한다 24 | // vector 타입의 첨자는 0번부터 시작하므로 1을 더해야 하는 점에 주의한다 25 | B[i] = lower_bound(T.begin(), T.end(), A[i]) - T.begin(); 26 | B[i] += 1; 27 | } 28 | 29 | // 답을 공백으로 구분해서 출력 30 | for (int i = 1; i <= N; i++) { 31 | if (i >= 2) cout << " "; 32 | cout << B[i]; 33 | } 34 | cout << endl; 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /editorial/chap02/cpp/answer_B06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N, A[100009]; 5 | int Q, L[100009], R[100009]; 6 | int Atari[100009], Hazre[100009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> N; 11 | for (int i = 1; i <= N; i++) cin >> A[i]; 12 | cin >> Q; 13 | for (int i = 1; i <= Q; i++) cin >> L[i] >> R[i]; 14 | 15 | // Atari・Hazre 개수의 누적 합계를 구합니다. 16 | Atari[0] = 0; 17 | Hazre[0] = 0; 18 | for (int i = 1; i <= N; i++) { 19 | Atari[i] = Atari[i - 1]; if (A[i] == 1) Atari[i] += 1; 20 | Hazre[i] = Hazre[i - 1]; if (A[i] == 0) Hazre[i] += 1; 21 | } 22 | 23 | // 질문에 답한다 24 | for (int i = 1; i <= Q; i++) { 25 | int NumAtari = Atari[R[i]] - Atari[L[i] - 1]; 26 | int NumHazre = Hazre[R[i]] - Hazre[L[i] - 1]; 27 | if (NumAtari > NumHazre) cout << "win" << endl; 28 | else if (NumAtari == NumHazre) cout << "draw" << endl; 29 | else cout << "lose" << endl; 30 | } 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /codes/python/chap04/answer_A23.py: -------------------------------------------------------------------------------- 1 | # 입력(배열 A는 0번부터 시작한다는 점에 유의!) 2 | N, M = map(int, input().split()) 3 | A = [ None ] * M 4 | for i in range(0, M): 5 | A[i] = list(map(int, input().split())) 6 | 7 | # 배열 초기화 8 | dp = [ [ 10 ** 9 ] * (2 ** N) for i in range(M + 1) ] 9 | 10 | # 동적 계획 알고리즘 11 | dp[0][0] = 0 12 | for i in range(1, M+1): 13 | for j in range(0, 2 ** N): 14 | # already[k] = 1일 때, 물품 k는 이미 무료 상태다 15 | already = [ None ] * N 16 | for k in range(0, N): 17 | if (j // (2 ** k)) % 2 == 0: 18 | already[k] = 0 19 | else: 20 | already[k] = 1 21 | 22 | # 쿠폰 i를 선택한 경우의 정수 표현 v를 계산한다 23 | v = 0 24 | for k in range(0, N): 25 | if already[k] == 1 or A[i-1][k] == 1: 26 | v += (2 ** k) 27 | 28 | # 이동을 수행한다 29 | dp[i][j] = min(dp[i][j], dp[i-1][j]) 30 | dp[i][v] = min(dp[i][v], dp[i-1][j] + 1) 31 | 32 | # 출력 33 | if dp[M][2 ** N - 1] == 1000000000: 34 | print("-1") 35 | else: 36 | print(dp[M][2 ** N - 1]) 37 | -------------------------------------------------------------------------------- /editorial/chap03/python/answer_B14.py: -------------------------------------------------------------------------------- 1 | import bisect 2 | import sys 3 | 4 | # "배열 A에 있는 카드 중 몇 개를 선택했을 때의 합계"로 생각되는 것을 열거한다 5 | # 비트 완전 탐색 사용 6 | def Enumerate(A): 7 | SumList = [] 8 | for i in range(2 ** len(A)): 9 | sum = 0 # 현재 합계 값 10 | for j in range(len(A)): 11 | wari = (2 ** j) 12 | if (i // wari) % 2 == 1: 13 | sum += A[j] 14 | SumList.append(sum) 15 | return SumList 16 | 17 | # 입력 18 | N, K = map(int, input().split()) 19 | A = list(map(int, input().split())) 20 | 21 | # 카드를 반으로 나눈다 22 | L1 = A[0:(N//2)] 23 | L2 = A[(N//2):N] 24 | 25 | # 각각에 대해 '가능한 카드의 합계'를 모두 열거한다 26 | Sum1 = Enumerate(L1) 27 | Sum2 = Enumerate(L2) 28 | Sum1.sort() 29 | Sum2.sort() 30 | 31 | # 바이너리 서치에서 Sum1[i] + Sum2[j] = K가 되는 것이 존재하는지 찾기 32 | for i in range(len(Sum1)): 33 | pos = bisect.bisect_left(Sum2, K-Sum1[i]) 34 | if pos int: 16 | # path halving 17 | while True: 18 | if uf[i] < 0: 19 | return i 20 | if uf[uf[i]] < 0: 21 | return uf[i] 22 | uf[i] = uf[uf[i]] 23 | i = uf[i] 24 | def unite(i: int, j: int) -> bool: 25 | i = root(i) 26 | j = root(j) 27 | if i == j: 28 | return False 29 | # 병합기술 (union by size) 30 | if uf[i] > uf[j]: 31 | i, j = j, i 32 | uf[i] += uf[j] 33 | uf[j] = i 34 | return True 35 | 36 | # 크라스칼법 37 | ans = 0 38 | for A, B, C in edge: 39 | if unite(A, B): 40 | ans += C 41 | 42 | print(ans) 43 | -------------------------------------------------------------------------------- /codes/cpp/chap07/code_7-10.cpp: -------------------------------------------------------------------------------- 1 | void Yamanobori() { 2 | // 변수 설정(5.95초 동안 루프를 돌린다/ CLOCKS_PER_SEC는 1초가 몇 밀리초인지를 나타낸다) 3 | int TIMELIMIT = 5.95 * CLOCKS_PER_SEC; 4 | int CurrentScore = GetScore(); 5 | int ti = clock(); 6 | 7 | // 등산 알고리즘 시작 8 | while (clock() - ti < TIMELIMIT) { 9 | // (t, new_x, new_y, new_h) 조합을 무작위로 선택한다 10 | // 함수 RandInt은 7.2절의 해답 예를 참조한다 11 | int t = RandInt(1, Q); 12 | int old_x = X[t], new_x = X[t] + RandInt(-9, 9); 13 | int old_y = Y[t], new_y = Y[t] + RandInt(-9, 9); 14 | int old_h = H[t], new_h = H[t] + RandInt(-19, 19); 15 | if (new_x < 0 || new_x >= N) continue; 16 | if (new_y < 0 || new_y >= N) continue; 17 | if (new_h <= 0 || new_h > N) continue; 18 | 19 | // 일단 변경하고, 점수를 평가한다 20 | Change(t, new_x, new_y, new_h); 21 | int NewScore = GetScore(); 22 | 23 | // 점수에 따라 채용 여부를 결정한다 24 | if (CurrentScore < NewScore) CurrentScore = NewScore; 25 | else Change(t, old_x, old_y, old_h); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /editorial/chap09/python/answer_B64.py: -------------------------------------------------------------------------------- 1 | from heapq import heappush, heappop 2 | 3 | N, M = map(int, input().split()) 4 | g = [[] for _ in range(N)] 5 | for _ in range(M): 6 | A, B, C = map(int, input().split()) 7 | A -= 1 8 | B -= 1 9 | g[A].append((B, C)) 10 | g[B].append((A, C)) 11 | 12 | INF = 1 << 61 13 | cost = [INF] * N 14 | back = [-1] * N 15 | q = [] 16 | 17 | # 정점에 도달하는 부분을 함수로 잘라내기 18 | def push(prev: int, i: int, c: int): 19 | if cost[i] <= c: 20 | return 21 | cost[i] = c 22 | back[i] = prev 23 | heappush(q, (c, i)) 24 | 25 | # 복원의 편의를 위해 뒤에서 Dijkstra 방법 26 | push(-1, N - 1, 0) 27 | while q: 28 | c, x = heappop(q) 29 | if cost[x] != c: 30 | continue # 같은 정점에서 여러 번 탐색하지 않음 (최악의 Θ(N^2) 시간 소요) 31 | for j, d in g[x]: 32 | push(x, j, c + d) 33 | 34 | # 최단 경로 복원 35 | ans = [0] 36 | while ans[-1] != N - 1: 37 | ans.append(back[ans[-1]]) 38 | 39 | for x in ans: 40 | print(x + 1) -------------------------------------------------------------------------------- /codes/java/chap02/answer_A10.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력(전반부) 8 | int N = sc.nextInt(); 9 | int[] A = new int[N + 1]; 10 | for (int i = 1; i <= N; i++) A[i] = sc.nextInt(); 11 | 12 | // 입력(후반부) 13 | int D = sc.nextInt(); 14 | int[] L = new int[D + 1]; 15 | int[] R = new int[D + 1]; 16 | for (int d = 1; d <= D; d++) { 17 | L[d] = sc.nextInt(); 18 | R[d] = sc.nextInt(); 19 | } 20 | 21 | // P[i]를 구한다 22 | int[] P = new int[N + 1]; 23 | P[1] = A[1]; 24 | for (int i = 2; i <= N; i++) P[i] = Math.max(P[i - 1], A[i]); 25 | 26 | // Q[i]를 구한다 27 | int[] Q = new int[N + 1]; 28 | Q[N] = A[N]; 29 | for (int i = N - 1; i >= 1; i--) Q[i] = Math.max(Q[i + 1], A[i]); 30 | 31 | // 각 날짜에 대해 답을 구한다 32 | for (int d = 1; d <= D; d++) { 33 | System.out.println(Math.max(P[L[d]-1], Q[R[d]+1])); 34 | } 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /codes/cpp/chap09/answer_A62.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int N, M, A[100009], B[100009]; 7 | vector G[100009]; 8 | bool visited[100009]; // 노드 x가 파란색일 경우, visited[x] = true 9 | 10 | void dfs(int pos) { // pos는 현재 위치 11 | visited[pos] = true; 12 | for (int i = 0; i < G[pos].size(); i++) { 13 | int nex = G[pos][i]; 14 | if (visited[nex] == false) dfs(nex); 15 | } 16 | return; 17 | } 18 | 19 | int main() { 20 | // 입력 21 | cin >> N >> M; 22 | for (int i = 1; i <= M; i++) { 23 | cin >> A[i] >> B[i]; 24 | G[A[i]].push_back(B[i]); 25 | G[B[i]].push_back(A[i]); 26 | } 27 | 28 | // 깊이 우선 탐색 29 | for (int i = 1; i <= N; i++) visited[i] = false; 30 | dfs(1); 31 | 32 | // 답 출력 33 | string Answer = "The graph is connected."; 34 | for (int i = 1; i <= N; i++) { 35 | if (visited[i] == false) Answer = "The graph is not connected."; 36 | } 37 | cout << Answer << endl; 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /codes/cpp/chap10/answer_A76.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const long long mod = 1000000007; 6 | long long N, W, L, R, X[150009]; 7 | int dp[150009], sum[150009]; 8 | 9 | int main() { 10 | // 입력 11 | cin >> N >> W >> L >> R; 12 | for (int i = 1; i <= N; i++) cin >> X[i]; 13 | 14 | // 서쪽 끝을 징검다리 0, 동쪽 끝을 징검다리 N+1로 간주한다 15 | X[0] = 0; X[N + 1] = W; 16 | 17 | // 동적 계획 알고리즘・출력 18 | dp[0] = 1; sum[0] = 1; 19 | for (int i = 1; i <= N + 1; i++) { 20 | int posL = lower_bound(X, X + N + 2, X[i] - R) - X; 21 | int posR = lower_bound(X, X + N + 2, X[i] - L + 1) - X; posR--; 22 | 23 | // dp[i]의 값을 누적 합으로 계산(뺄셈 한 뒤 나머지를 구하는 것에 주의!) 24 | if (posR == -1) dp[i] = 0; 25 | else dp[i] = sum[posR]; 26 | if (posL >= 1) dp[i] -= sum[posL - 1]; 27 | dp[i] = (dp[i] + mod) % mod; 28 | 29 | // 누적 합 sum[i]를 업데이트 30 | sum[i] = sum[i - 1] + dp[i]; 31 | sum[i] %= mod; 32 | } 33 | cout << dp[N + 1] << endl; 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /codes/python/chap04/answer_A21.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N = int(input()) 3 | P = [ None ] * (N + 1) 4 | A = [ None ] * (N + 1) 5 | for i in range(1, N+1): 6 | P[i], A[i] = map(int, input().split()) 7 | 8 | # 동적 계획 알고리즘(LEN은 r-l의 값) 9 | dp = [ [ None ] * (N + 1) for i in range(N + 1) ] 10 | dp[1][N] = 0 11 | for LEN in reversed(range(0, N-1)): 12 | for l in range(1, N-LEN+1): 13 | r = l + LEN 14 | 15 | # score1의 값(l-1번째의 블록을 제거했을 때의 득점)을 구한다 16 | score1 = 0 17 | if l>=2 and l<=P[l-1] and P[l-1]<=r: 18 | score1 = A[l-1] 19 | 20 | # score2의 값(r+1번째의 블록을 제거했을 때의 득점)을 구한다 21 | score2 = 0 22 | if r<=N-1 and l<=P[r+1] and P[r+1]<=r: 23 | score2 = A[r+1] 24 | 25 | # dp[l][r]을 구한다 26 | if l==1: 27 | dp[l][r] = dp[l][r+1] + score2 28 | elif r==N: 29 | dp[l][r] = dp[l-1][r] + score1 30 | else: 31 | dp[l][r] = max(dp[l-1][r] + score1, dp[l][r+1] + score2) 32 | 33 | # 출력 34 | Answer = 0 35 | for i in range(1, N+1): 36 | Answer = max(Answer, dp[i][i]) 37 | print(Answer) 38 | -------------------------------------------------------------------------------- /editorial/final/cpp/answer_C12.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int N, K; 6 | int M, A[59], B[59]; 7 | int dp[19][309]; 8 | 9 | // l 페이지와 r 페이지 사이에 몇 개의 연결고리가 있는가? 10 | int tsunagari(int l, int r) { 11 | int cnt = 0; 12 | for (int i = 1; i <= M; i++) { 13 | if (l <= A[i] && B[i] <= r) cnt++; 14 | } 15 | return cnt; 16 | } 17 | 18 | int main() { 19 | // 입력 20 | cin >> N >> M >> K; 21 | for (int i = 1; i <= M; i++) cin >> A[i] >> B[i]; 22 | 23 | // 배열 dp 초기화 24 | for (int i = 0; i <= K; i++) { 25 | for (int j = 0; j <= N; j++) dp[i][j] = -1000000; 26 | } 27 | 28 | // 동적 계획 알고리즘(받는 전환 형식) 29 | dp[0][0] = 0; 30 | for (int i = 1; i <= K; i++) { 31 | for (int j = 1; j <= N; j++) { 32 | // k는 '이전 장이 어느 페이지에서 끝났는지' 33 | for (int k = 0; k <= j - 1; k++) { 34 | dp[i][j] = max(dp[i][j], dp[i - 1][k] + tsunagari(k + 1, j)); 35 | } 36 | } 37 | } 38 | 39 | // 출력 40 | cout << dp[K][N] << endl; 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /codes/java/chap04/answer_A20.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력(문자열은 0번째 문자부터 시작하는 것에 주의!) 8 | String S = sc.next(); int N = S.length(); 9 | String T = sc.next(); int M = T.length(); 10 | 11 | // 배열 dp의 정의 12 | int[][] dp = new int[N + 1][M + 1]; 13 | 14 | // 동적 계획 알고리즘 15 | dp[0][0] = 0; 16 | for (int i = 0; i <= N; i++) { 17 | for (int j = 0; j <= M; j++) { 18 | if (i >= 1 && j >= 1 && S.charAt(i-1) == T.charAt(j-1)) { 19 | dp[i][j] = Math.max(dp[i - 1][j], Math.max(dp[i][j - 1], dp[i - 1][j - 1] + 1)); 20 | } 21 | else if (i >= 1 && j >= 1) { 22 | dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); 23 | } 24 | else if (i >= 1) { 25 | dp[i][j] = dp[i - 1][j]; 26 | } 27 | else if (j >= 1) { 28 | dp[i][j] = dp[i][j - 1]; 29 | } 30 | } 31 | } 32 | 33 | // 출력 34 | System.out.println(dp[N][M]); 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /codes/java/chap06/answer_A44.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int Q = sc.nextInt(); 10 | 11 | // 배열 초기화 12 | int State = 1; 13 | int[] E = new int[N + 1]; 14 | for (int i = 1; i <= N; i++) E[i] = i; 15 | 16 | // 쿼리 처리 17 | for (int i = 1; i <= Q; i++) { 18 | int Type, x, y; 19 | Type = sc.nextInt(); 20 | 21 | // [1] 변경 조작 22 | if (Type == 1) { 23 | x = sc.nextInt(); 24 | y = sc.nextInt(); 25 | if (State == 1) E[x] = y; 26 | if (State == 2) E[N+1-x] = y; 27 | } 28 | 29 | // [2] 반전 조작 30 | if (Type == 2) { 31 | if (State == 1) State = 2; 32 | else State = 1; 33 | } 34 | 35 | // [3] 취득 조작 36 | if (Type == 3) { 37 | x = sc.nextInt(); 38 | if (State == 1) System.out.println(E[x]); 39 | if (State == 2) System.out.println(E[N + 1 - x]); 40 | } 41 | } 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /editorial/final/cpp/answer_C11.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | long long N, K; 6 | double A[100009]; 7 | 8 | // 나눗셈의 값이 x일 때 의석수는? 9 | long long check(double x) { 10 | long long sum = 0; 11 | for (int i = 1; i <= N; i++) sum += (long long)(A[i] / x); 12 | return sum; 13 | } 14 | 15 | int main() { 16 | // 입력 17 | cin >> N >> K; 18 | for (int i = 1; i <= N; i++) cin >> A[i]; 19 | 20 | // 바이너리 서치 21 | double Left = 1, Right = 1000000000, Mid; 22 | double Border = 0; // 현재 경계선(총 의석수가 K 이상인 최대값) 23 | for (int i = 1; i <= 60; i++) { 24 | Mid = (Left + Right) / 2.0; 25 | 26 | // 분할 값이 Mid보다 큰가? 27 | long long val = check(Mid); 28 | if (val >= K) { 29 | Left = Mid; 30 | Border = max(Border, Mid); 31 | } 32 | else { 33 | Right = Mid; 34 | } 35 | } 36 | 37 | // 출력 38 | for (int i = 1; i <= N; i++) { 39 | if (i >= 2) cout << " "; 40 | cout << (long long)(A[i] / Border); 41 | } 42 | cout << endl; 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /codes/cpp/chap02/answer_A08.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int H, W, Q; 5 | int X[1509][1509], Z[1509][1509]; 6 | int A[100009], B[100009], C[100009], D[100009]; 7 | 8 | int main() { 9 | // 입력 10 | cin >> H >> W; 11 | for (int i = 1; i <= H; i++) { 12 | for (int j = 1; j <= W; j++) cin >> X[i][j]; 13 | } 14 | cin >> Q; 15 | for (int i = 1; i <= Q; i++) cin >> A[i] >> B[i] >> C[i] >> D[i]; 16 | 17 | // 배열 Z 초기화 18 | for (int i = 0; i <= H; i++) { 19 | for (int j = 0; j <= W; j++) Z[i][j] = 0; 20 | } 21 | 22 | // 가로 방향으로 누적 합을 구한다 23 | for (int i = 1; i <= H; i++) { 24 | for (int j = 1; j <= W; j++) Z[i][j] = Z[i][j - 1] + X[i][j]; 25 | } 26 | 27 | // 세로 방향으로 누적 합을 구한다 28 | for (int j = 1; j <= W; j++) { 29 | for (int i = 1; i <= H; i++) Z[i][j] = Z[i - 1][j] + Z[i][j]; 30 | } 31 | 32 | // 답을 구한다 33 | for (int i = 1; i <= Q; i++) { 34 | cout << Z[C[i]][D[i]] + Z[A[i] - 1][B[i] - 1] - Z[A[i] - 1][D[i]] - Z[C[i]][B[i] - 1] << endl; 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /codes/java/chap04/answer_A19.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int W = sc.nextInt(); 10 | int[] w = new int[N + 1]; 11 | int[] v = new int[N + 1]; 12 | for (int i = 1; i <= N; i++) { 13 | w[i] = sc.nextInt(); 14 | v[i] = sc.nextInt(); 15 | } 16 | 17 | // 배열 dp 정의 및 초기화 18 | long[][] dp = new long[N + 1][W + 1]; 19 | for (int i = 0; i <= N; i++) { 20 | for (int j = 0; j <= W; j++) dp[i][j] = -1000000000000L; 21 | } 22 | 23 | // 동적 계획 알고리즘 24 | dp[0][0] = 0; 25 | for (int i = 1; i <= N; i++) { 26 | for (int j = 0; j <= W; j++) { 27 | if (j < w[i]) dp[i][j] = dp[i - 1][j]; 28 | else dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i]); 29 | } 30 | } 31 | 32 | // 출력 33 | long Answer = 0; 34 | for (int i = 0; i <= W; i++) Answer = Math.max(Answer, dp[N][i]); 35 | System.out.println(Answer); 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /codes/java/chap06/answer_A42.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int K = sc.nextInt(); 10 | int[] A = new int[N + 1]; 11 | int[] B = new int[N + 1]; 12 | for (int i = 1; i <= N; i++) { 13 | A[i] = sc.nextInt(); 14 | B[i] = sc.nextInt(); 15 | } 16 | 17 | // (a, b)쌍을 완전 탐색 18 | int Answer = 0; 19 | for (int a = 1; a <= 100; a++) { 20 | for (int b = 1; b <= 100; b++) { 21 | int Score = GetScore(a, b, N, K, A, B); 22 | Answer = Math.max(Answer, Score); 23 | } 24 | } 25 | 26 | // 출력 27 | System.out.println(Answer); 28 | } 29 | 30 | // 정수의 쌍(a, b)가 결정되었을 때 참가 가능한 학생 수를 반환하는 함수 31 | static int GetScore(int a, int b, int N, int K, int[] A, int[] B) { 32 | int cnt = 0; 33 | for (int i = 1; i <= N; i++) { 34 | if (a<=A[i] && A[i]<=a+K && b<=B[i] && B[i]<=b+K) { 35 | cnt += 1; 36 | } 37 | } 38 | return cnt; 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /editorial/final/cpp/answer_C18.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int N, A[409]; 7 | int dp[409][409]; 8 | 9 | int main() { 10 | // 입력 11 | cin >> N; 12 | for (int i = 1; i <= 2 * N; i++) cin >> A[i]; 13 | 14 | // 배열 dp 초기화 15 | for (int i = 1; i <= 2 * N; i++) { 16 | for (int j = 1; j <= 2 * N; j++) dp[i][j] = 1000000000; 17 | } 18 | 19 | // 동적 계획 알고리즘(초기 상태) 20 | for (int i = 1; i <= 2 * N - 1; i++) { 21 | dp[i][i + 1] = abs(A[i] - A[i + 1]); 22 | } 23 | 24 | // 동적 계획 알고리즘(전이) 25 | for (int LEN = 2; LEN <= 2 * N - 1; LEN++) { 26 | for (int l = 1; l <= 2 * N - LEN; l++) { 27 | int r = l + LEN; 28 | 29 | // l번째와 r번째를 지우는 경우 30 | dp[l][r] = min(dp[l][r], dp[l + 1][r - 1] + abs(A[l] - A[r])); 31 | 32 | // 2개의 구간을 합성시키는 경우 33 | for (int m = l; m < r; m++) { 34 | dp[l][r] = min(dp[l][r], dp[l][m] + dp[m + 1][r]); 35 | } 36 | } 37 | } 38 | 39 | // 출력 40 | cout << dp[1][2 * N] << endl; 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /codes/java/chap04/answer_A18.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner sc = new Scanner(System.in); 6 | 7 | // 입력 8 | int N = sc.nextInt(); 9 | int S = sc.nextInt(); 10 | int[] A = new int[N + 1]; 11 | for (int i = 1; i <= N; i++) A[i] = sc.nextInt(); 12 | 13 | // 배열 dp의 정의 14 | boolean[][] dp = new boolean[N + 1][S + 1]; 15 | 16 | // 동적 계획 알고리즘(i = 0) 17 | dp[0][0] = true; 18 | for (int i = 1; i <= S; i++) dp[0][i] = false; 19 | 20 | // 동적 계획 알고리즘(i >= 1) 21 | for (int i = 1; i <= N; i++) { 22 | for (int j = 0; j <= S; j++) { 23 | if (j < A[i]) { 24 | if (dp[i - 1][j] == true) dp[i][j] = true; 25 | else dp[i][j] = false; 26 | } 27 | if (j >= A[i]) { 28 | if (dp[i - 1][j] == true || dp[i - 1][j - A[i]] == true) dp[i][j] = true; 29 | else dp[i][j] = false; 30 | } 31 | } 32 | } 33 | 34 | // 출력 35 | if (dp[N][S] == true) System.out.println("Yes"); 36 | else System.out.println("No"); 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /editorial/chap06/cpp/answer_B42.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | long long N; 6 | long long A[100009], B[100009]; 7 | 8 | // omote=1일 때 앞면의 합계가 양수, ura=1일 때 뒤쪽의 합계가 양수 9 | // omote=2일 때 앞면의 합계가 음수, ura=2일 때 뒤쪽의 합계가 음수 10 | long long solve(int omote, int ura) { 11 | long long sum = 0; 12 | for (int i = 1; i <= N; i++) { 13 | long long card1 = A[i]; if (omote == 2) card1 = -A[i]; 14 | long long card2 = B[i]; if (ura == 2) card2 = -B[i]; 15 | // 카드 i를 선택해야 할까? 16 | if (card1 + card2 >= 0) { 17 | sum += (card1 + card2); 18 | } 19 | } 20 | return sum; 21 | } 22 | 23 | int main() { 24 | // 입력 25 | cin >> N; 26 | for (int i = 1; i <= N; i++) cin >> A[i] >> B[i]; 27 | 28 | // 앞의 총합의 양과 음, 뒤의 총합의 양과 음을 완벽 탐색 29 | long long Answer1 = solve(1, 1); 30 | long long Answer2 = solve(1, 2); 31 | long long Answer3 = solve(2, 1); 32 | long long Answer4 = solve(2, 2); 33 | 34 | // 답을 출력 35 | cout << max({ Answer1,Answer2,Answer3,Answer4 }) << endl; 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /editorial/chap08/python/answer_B58.py: -------------------------------------------------------------------------------- 1 | import bisect 2 | 3 | 4 | INF = 1 << 61 5 | siz = 1 << 17 6 | dat = [INF] * (siz * 2) 7 | 8 | # 대입 seg[i] = v 9 | def update(i: int, v: int) -> None: 10 | i += siz 11 | dat[i] = v 12 | while i > 1: 13 | i >>= 1 14 | dat[i] = min(dat[i * 2], dat[i * 2 + 1]) 15 | 16 | # min(seg[l], seg[l + 1], ..., seg[r - 1])을 구한다 17 | def query(l: int, r: int) -> int: 18 | l += siz 19 | r += siz 20 | answer = INF 21 | while l < r: 22 | if l & 1: 23 | if answer > dat[l]: 24 | answer = dat[l] 25 | l += 1 26 | if r & 1: 27 | r -= 1 28 | if answer > dat[r]: 29 | answer = dat[r] 30 | l >>= 1 31 | r >>= 1 32 | return answer 33 | 34 | # 입력 35 | N, L, R = map(int, input().split()) 36 | X = list(map(int, input().split())) 37 | dp = [0] * N 38 | 39 | # 동적 계획 알고리즘 40 | update(0, 0) 41 | for i in range(1, N): 42 | x = X[i] 43 | posL = bisect.bisect_left(X, x - R) 44 | posR = bisect.bisect_right(X, x - L) 45 | dp[i] = query(posL, posR) + 1 46 | update(i, dp[i]) 47 | 48 | print(dp[-1]) 49 | -------------------------------------------------------------------------------- /codes/python/chap08/answer_A57.py: -------------------------------------------------------------------------------- 1 | # 입력 2 | N, Q = map(int, input().split()) 3 | A = list(map(int, input().split())) 4 | queries = [ list(map(int, input().split())) for i in range(Q) ] 5 | 6 | # 사전 계산(여기서는 책과 달리 0-indexed로 구현했다) 7 | LEVELS = 30 8 | dp = [ [ None ] * N for i in range(LEVELS) ] 9 | for i in range(0, N): 10 | dp[0][i] = A[i] - 1 11 | for d in range(1, LEVELS): 12 | for i in range(0, N): 13 | dp[d][i] = dp[d - 1][dp[d - 1][i]] 14 | 15 | # 쿼리 처리(여기서는 책과 달리 0-indexed로 구현했다) 16 | for X, Y in queries: 17 | current_place = X - 1 18 | for d in range(29, -1, -1): 19 | if ((Y >> d) & 1) == 1: 20 | current_place = dp[d][current_place] 21 | print(current_place + 1) # current_place는 0-indexed로 계산했으므로 1을 더하여 출력한다 22 | 23 | # 참고 1: 책의 C++ 프로그램에서 'Y의 2^d의 위치 찾기'는 C++에서는 (Y / (1 << d)) % 2로 구현되어 있었다. 24 | # 파이썬에서도 19번째 줄은 (Y // (2 ** d)) % 2로 구현할 수 있지만, ((Y >> d) & 1)로 계산하는 것이 상수배 측면에서 더 빠르다. 25 | # 참고 2: 이 프로그램의 평균 실행시간은 2초를 겨우 넘기는 정도이며, 제출에 따라서는 TLE가 될 수도 있습니다. 26 | # 같은 프로그램을 PyPy3로 제출하면 0.5초 정도의 실행시간으로 AC 할 수 있다. --------------------------------------------------------------------------------