├── README.md ├── codes ├── cpp │ ├── chap01 │ │ ├── answer_A01.cpp │ │ ├── answer_A02.cpp │ │ ├── answer_A03.cpp │ │ ├── answer_A04.cpp │ │ ├── answer_A05.cpp │ │ ├── code_1-01.cpp │ │ ├── code_1-02.cpp │ │ ├── code_1-03.cpp │ │ └── code_1-04.cpp │ ├── chap02 │ │ ├── answer_A06.cpp │ │ ├── answer_A07.cpp │ │ ├── answer_A08.cpp │ │ ├── answer_A09.cpp │ │ ├── answer_A10.cpp │ │ └── code_2-01.cpp │ ├── chap03 │ │ ├── answer_A11.cpp │ │ ├── answer_A12.cpp │ │ ├── answer_A13.cpp │ │ ├── answer_A14.cpp │ │ ├── answer_A15.cpp │ │ ├── code_3-01.cpp │ │ └── code_3-02.cpp │ ├── chap04 │ │ ├── answer_A16.cpp │ │ ├── answer_A17.cpp │ │ ├── answer_A18.cpp │ │ ├── answer_A19.cpp │ │ ├── answer_A20.cpp │ │ ├── answer_A21.cpp │ │ ├── answer_A22.cpp │ │ ├── answer_A23.cpp │ │ ├── answer_A24.cpp │ │ ├── answer_A24_withoutDP.cpp │ │ ├── answer_A25.cpp │ │ └── code_4-01.cpp │ ├── chap05 │ │ ├── answer_A26.cpp │ │ ├── answer_A27.cpp │ │ ├── answer_A28.cpp │ │ ├── answer_A29.cpp │ │ ├── answer_A30.cpp │ │ ├── answer_A31.cpp │ │ ├── answer_A32.cpp │ │ ├── answer_A33.cpp │ │ ├── answer_A34.cpp │ │ ├── answer_A35.cpp │ │ ├── code_5-01.cpp │ │ ├── code_5-02.cpp │ │ ├── code_5-03.cpp │ │ ├── code_5-04.cpp │ │ └── code_5-05.cpp │ ├── chap06 │ │ ├── answer_A36.cpp │ │ ├── answer_A37.cpp │ │ ├── answer_A38.cpp │ │ ├── answer_A39.cpp │ │ ├── answer_A40.cpp │ │ ├── answer_A41.cpp │ │ ├── answer_A42.cpp │ │ ├── answer_A43.cpp │ │ ├── answer_A44.cpp │ │ ├── answer_A45.cpp │ │ ├── code_6-01.cpp │ │ └── code_6-02.cpp │ ├── chap07 │ │ ├── answer_A46.cpp │ │ ├── answer_A47.cpp │ │ ├── answer_A48.cpp │ │ ├── answer_A49.cpp │ │ ├── answer_A49_greedy1_37454pts.cpp │ │ ├── answer_A49_greedy2_40978pts.cpp │ │ ├── answer_A50.cpp │ │ ├── code_7-01.cpp │ │ ├── code_7-02.cpp │ │ ├── code_7-03.cpp │ │ ├── code_7-04.cpp │ │ ├── code_7-05.cpp │ │ ├── code_7-06.cpp │ │ ├── code_7-07.cpp │ │ ├── code_7-08.cpp │ │ ├── code_7-09.cpp │ │ ├── code_7-10.cpp │ │ ├── code_7-11.cpp │ │ ├── code_7-12.cpp │ │ ├── code_7-13.cpp │ │ └── code_7-14.cpp │ ├── chap08 │ │ ├── answer_A51.cpp │ │ ├── answer_A52.cpp │ │ ├── answer_A53.cpp │ │ ├── answer_A54.cpp │ │ ├── answer_A55.cpp │ │ ├── answer_A56.cpp │ │ ├── answer_A57.cpp │ │ ├── answer_A58.cpp │ │ ├── answer_A59.cpp │ │ ├── answer_A60.cpp │ │ ├── code_8-01.cpp │ │ ├── code_8-02.cpp │ │ ├── code_8-03.cpp │ │ ├── code_8-04.cpp │ │ ├── code_8-05.cpp │ │ └── code_8-06.cpp │ ├── chap09 │ │ ├── answer_A61.cpp │ │ ├── answer_A62.cpp │ │ ├── answer_A63.cpp │ │ ├── answer_A64.cpp │ │ ├── answer_A65.cpp │ │ ├── answer_A65_BFS.cpp │ │ ├── answer_A65_DFS.cpp │ │ ├── answer_A66.cpp │ │ ├── answer_A67.cpp │ │ ├── answer_A68.cpp │ │ ├── answer_A69.cpp │ │ ├── answer_A70.cpp │ │ ├── code_9-01.cpp │ │ ├── code_9-02.cpp │ │ ├── code_9-03.cpp │ │ ├── code_9-04.cpp │ │ └── code_9-05.cpp │ └── chap10 │ │ ├── answer_A71.cpp │ │ ├── answer_A72.cpp │ │ ├── answer_A73.cpp │ │ ├── answer_A74.cpp │ │ ├── answer_A75.cpp │ │ ├── answer_A76.cpp │ │ ├── answer_A77.cpp │ │ ├── code_10-01.cpp │ │ └── code_10-02.cpp ├── java │ ├── chap01 │ │ ├── answer_A01.java │ │ ├── answer_A02.java │ │ ├── answer_A03.java │ │ ├── answer_A04.java │ │ └── answer_A05.java │ ├── chap02 │ │ ├── answer_A06.java │ │ ├── answer_A07.java │ │ ├── answer_A08.java │ │ ├── answer_A09.java │ │ └── answer_A10.java │ ├── chap03 │ │ ├── answer_A11.java │ │ ├── answer_A12.java │ │ ├── answer_A13.java │ │ ├── answer_A14.java │ │ └── answer_A15.java │ ├── chap04 │ │ ├── answer_A16.java │ │ ├── answer_A17.java │ │ ├── answer_A18.java │ │ ├── answer_A19.java │ │ ├── answer_A20.java │ │ ├── answer_A21.java │ │ ├── answer_A22.java │ │ ├── answer_A23.java │ │ ├── answer_A24.java │ │ └── answer_A25.java │ ├── chap05 │ │ ├── answer_A26.java │ │ ├── answer_A27.java │ │ ├── answer_A28.java │ │ ├── answer_A29.java │ │ ├── answer_A30.java │ │ ├── answer_A31.java │ │ ├── answer_A32.java │ │ ├── answer_A33.java │ │ ├── answer_A34.java │ │ └── answer_A35.java │ ├── chap06 │ │ ├── answer_A36.java │ │ ├── answer_A37.java │ │ ├── answer_A38.java │ │ ├── answer_A39.java │ │ ├── answer_A40.java │ │ ├── answer_A41.java │ │ ├── answer_A42.java │ │ ├── answer_A43.java │ │ ├── answer_A44.java │ │ └── answer_A45.java │ ├── chap07 │ │ ├── answer_A46.java │ │ ├── answer_A47.java │ │ ├── answer_A48.java │ │ ├── answer_A49.java │ │ ├── answer_A49_greedy1_37454pts.java │ │ ├── answer_A49_greedy2_40978pts.java │ │ ├── answer_A50.java │ │ └── answer_A50_extra.java │ ├── chap08 │ │ ├── answer_A51.java │ │ ├── answer_A52.java │ │ ├── answer_A53.java │ │ ├── answer_A54.java │ │ ├── answer_A55.java │ │ ├── answer_A56.java │ │ ├── answer_A57.java │ │ ├── answer_A58.java │ │ ├── answer_A59.java │ │ └── answer_A60.java │ ├── chap09 │ │ ├── answer_A61.java │ │ ├── answer_A62.java │ │ ├── answer_A63.java │ │ ├── answer_A64.java │ │ ├── answer_A65.java │ │ ├── answer_A66.java │ │ ├── answer_A67.java │ │ ├── answer_A68.java │ │ ├── answer_A69.java │ │ ├── answer_A70.java │ │ └── answer_A70_extra.java │ └── chap10 │ │ ├── answer_A71.java │ │ ├── answer_A72.java │ │ ├── answer_A73.java │ │ ├── answer_A74.java │ │ ├── answer_A75.java │ │ ├── answer_A76.java │ │ └── answer_A77.java └── python │ ├── chap01 │ ├── answer_A01.py │ ├── answer_A02.py │ ├── answer_A03.py │ ├── answer_A04.py │ └── answer_A05.py │ ├── chap02 │ ├── answer_A06.py │ ├── answer_A07.py │ ├── answer_A08.py │ ├── answer_A09.py │ └── answer_A10.py │ ├── chap03 │ ├── answer_A11.py │ ├── answer_A12.py │ ├── answer_A13.py │ ├── answer_A14.py │ └── answer_A15.py │ ├── chap04 │ ├── answer_A16.py │ ├── answer_A17.py │ ├── answer_A18.py │ ├── answer_A19.py │ ├── answer_A20.py │ ├── answer_A21.py │ ├── answer_A22.py │ ├── answer_A23.py │ ├── answer_A24.py │ ├── answer_A24_withoutDP.py │ └── answer_A25.py │ ├── chap05 │ ├── answer_A26.py │ ├── answer_A27.py │ ├── answer_A28.py │ ├── answer_A29.py │ ├── answer_A30.py │ ├── answer_A31.py │ ├── answer_A32.py │ ├── answer_A33.py │ ├── answer_A34.py │ └── answer_A35.py │ ├── chap06 │ ├── answer_A36.py │ ├── answer_A37.py │ ├── answer_A38.py │ ├── answer_A39.py │ ├── answer_A40.py │ ├── answer_A41.py │ ├── answer_A42.py │ ├── answer_A43.py │ ├── answer_A44.py │ └── answer_A45.py │ ├── chap07 │ ├── answer_A46.py │ ├── answer_A47.py │ ├── answer_A48.py │ ├── answer_A48_extra.py │ ├── answer_A49.py │ ├── answer_A49_greedy1_37454pts.py │ ├── answer_A49_greedy2_40978pts.py │ ├── answer_A50.py │ └── answer_A50_extra.py │ ├── chap08 │ ├── answer_A51.py │ ├── answer_A52.py │ ├── answer_A53.py │ ├── answer_A54.py │ ├── answer_A56.py │ ├── answer_A57.py │ ├── answer_A58.py │ ├── answer_A59.py │ └── answer_A60.py │ ├── chap09 │ ├── answer_A61.py │ ├── answer_A62.py │ ├── answer_A63.py │ ├── answer_A64.py │ ├── answer_A65.py │ ├── answer_A66.py │ ├── answer_A67.py │ ├── answer_A68.py │ ├── answer_A69.py │ ├── answer_A70.py │ └── answer_A70_extra.py │ └── chap10 │ ├── answer_A71.py │ ├── answer_A72.py │ ├── answer_A73.py │ ├── answer_A74.py │ ├── answer_A75.py │ ├── answer_A76.py │ └── answer_A77.py ├── editorial ├── Editorial_All.pdf ├── chap01 │ ├── chap01.pdf │ ├── cpp │ │ ├── answer_B01.cpp │ │ ├── answer_B02.cpp │ │ ├── answer_B03.cpp │ │ └── answer_B04.cpp │ └── python │ │ ├── answer_B01.py │ │ ├── answer_B02.py │ │ ├── answer_B03.py │ │ └── answer_B04.py ├── chap02 │ ├── chap02.pdf │ ├── cpp │ │ ├── answer_B06.cpp │ │ ├── answer_B07.cpp │ │ ├── answer_B08.cpp │ │ └── answer_B09.cpp │ └── python │ │ ├── answer_B06.py │ │ ├── answer_B07.py │ │ ├── answer_B08.py │ │ └── answer_B09.py ├── chap03 │ ├── chap03.pdf │ ├── cpp │ │ ├── answer_B11.cpp │ │ ├── answer_B12.cpp │ │ ├── answer_B13.cpp │ │ └── answer_B14.cpp │ └── python │ │ ├── answer_B11.py │ │ ├── answer_B12.py │ │ ├── answer_B13.py │ │ └── answer_B14.py ├── chap04 │ ├── chap04.pdf │ ├── cpp │ │ ├── answer_B16.cpp │ │ ├── answer_B17.cpp │ │ ├── answer_B18.cpp │ │ ├── answer_B19.cpp │ │ ├── answer_B20.cpp │ │ ├── answer_B21.cpp │ │ ├── answer_B22.cpp │ │ ├── answer_B23.cpp │ │ └── answer_B24.cpp │ └── python │ │ ├── answer_B16.py │ │ ├── answer_B17.py │ │ ├── answer_B18.py │ │ ├── answer_B19.py │ │ ├── answer_B20.py │ │ ├── answer_B21.py │ │ ├── answer_B22.py │ │ ├── answer_B23.py │ │ └── answer_B24.py ├── chap05 │ ├── answer_B26.cpp │ ├── answer_B26.py │ ├── answer_B27.cpp │ ├── answer_B27.py │ ├── answer_B28.cpp │ ├── answer_B28.py │ ├── answer_B29.cpp │ ├── answer_B29.py │ ├── answer_B30.cpp │ ├── answer_B30.py │ ├── answer_B31.cpp │ ├── answer_B31.py │ ├── answer_B32.cpp │ ├── answer_B32.py │ ├── answer_B33.cpp │ ├── answer_B33.py │ ├── answer_B34.cpp │ ├── answer_B34.py │ ├── chap05.pdf │ ├── cpp │ │ ├── answer_B26.cpp │ │ ├── answer_B27.cpp │ │ ├── answer_B28.cpp │ │ ├── answer_B29.cpp │ │ ├── answer_B30.cpp │ │ ├── answer_B31.cpp │ │ ├── answer_B32.cpp │ │ ├── answer_B33.cpp │ │ └── answer_B34.cpp │ └── python │ │ ├── answer_B26.py │ │ ├── answer_B27.py │ │ ├── answer_B28.py │ │ ├── answer_B29.py │ │ ├── answer_B30.py │ │ ├── answer_B31.py │ │ ├── answer_B32.py │ │ ├── answer_B33.py │ │ └── answer_B34.py ├── chap06 │ ├── chap06.pdf │ ├── cpp │ │ ├── answer_B36.cpp │ │ ├── answer_B37.cpp │ │ ├── answer_B38.cpp │ │ ├── answer_B39.cpp │ │ ├── answer_B40.cpp │ │ ├── answer_B41.cpp │ │ ├── answer_B42.cpp │ │ ├── answer_B43.cpp │ │ ├── answer_B44.cpp │ │ └── answer_B45.cpp │ └── python │ │ ├── answer_B36.py │ │ ├── answer_B37.py │ │ ├── answer_B38.py │ │ ├── answer_B39.py │ │ ├── answer_B40.py │ │ ├── answer_B41.py │ │ ├── answer_B42.py │ │ ├── answer_B43.py │ │ ├── answer_B44.py │ │ └── answer_B45.py ├── chap08 │ ├── chap08.pdf │ ├── cpp │ │ ├── answer_B51.cpp │ │ ├── answer_B52.cpp │ │ ├── answer_B53.cpp │ │ ├── answer_B54.cpp │ │ ├── answer_B55.cpp │ │ ├── answer_B56.cpp │ │ ├── answer_B57.cpp │ │ ├── answer_B58.cpp │ │ └── answer_B59.cpp │ └── python │ │ ├── answer_B51.py │ │ ├── answer_B52.py │ │ ├── answer_B53.py │ │ ├── answer_B54.py │ │ ├── answer_B55.py │ │ ├── answer_B56.py │ │ ├── answer_B57.py │ │ ├── answer_B58.py │ │ └── answer_B59.py ├── chap09 │ ├── chap09.pdf │ ├── cpp │ │ ├── answer_B61.cpp │ │ ├── answer_B62.cpp │ │ ├── answer_B63.cpp │ │ ├── answer_B64.cpp │ │ ├── answer_B65.cpp │ │ ├── answer_B66.cpp │ │ ├── answer_B67.cpp │ │ ├── answer_B68.cpp │ │ └── answer_B69.cpp │ └── python │ │ ├── answer_B61.py │ │ ├── answer_B62.py │ │ ├── answer_B63.py │ │ ├── answer_B64.py │ │ ├── answer_B65.py │ │ ├── answer_B66.py │ │ ├── answer_B67.py │ │ ├── answer_B68.py │ │ └── answer_B69.py └── final │ ├── cpp │ ├── answer_C01.cpp │ ├── answer_C02.cpp │ ├── answer_C03.cpp │ ├── answer_C04.cpp │ ├── answer_C05.cpp │ ├── answer_C06.cpp │ ├── answer_C07.cpp │ ├── answer_C08.cpp │ ├── answer_C09.cpp │ ├── answer_C10.cpp │ ├── answer_C11.cpp │ ├── answer_C12.cpp │ ├── answer_C13.cpp │ ├── answer_C14.cpp │ ├── answer_C15.cpp │ ├── answer_C16.cpp │ ├── answer_C17.cpp │ ├── answer_C18.cpp │ ├── answer_C19.cpp │ └── answer_C20.cpp │ ├── final_01-10.pdf │ └── final_11-20.pdf └── errata ├── errata_Chap0-4.md ├── errata_Chap5-7.md ├── errata_Chap8-10.md └── errata_editorialPDF.md /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/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/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/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 | -------------------------------------------------------------------------------- /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-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/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/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 | -------------------------------------------------------------------------------- /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/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/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/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/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/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/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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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/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/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/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 | -------------------------------------------------------------------------------- /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/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/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/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/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 | -------------------------------------------------------------------------------- /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_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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /codes/cpp/chap05/answer_A29.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // a の b 乗を m で割った余りを返す関数 5 | // 変数 a は 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 の 2^i 乗」が掛けられるとき 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/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/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/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 | -------------------------------------------------------------------------------- /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 した値(ニム和)を求める 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 | -------------------------------------------------------------------------------- /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/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/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/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 は 以下の最大の整数までループする) 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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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/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_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/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/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/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 | -------------------------------------------------------------------------------- /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/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/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/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/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/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-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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 のリセット(ゼロに戻す) 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 のリセット(ゼロに戻す) 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-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 | -------------------------------------------------------------------------------- /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/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-14.cpp: -------------------------------------------------------------------------------- 1 | // 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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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/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-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 | -------------------------------------------------------------------------------- /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/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/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/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/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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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/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/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 | -------------------------------------------------------------------------------- /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 | // Bellman-Ford 法 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/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/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/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 | -------------------------------------------------------------------------------- /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/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/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/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 | -------------------------------------------------------------------------------- /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/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/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/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/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 | -------------------------------------------------------------------------------- /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/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/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/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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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/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/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/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 | -------------------------------------------------------------------------------- /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/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_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 | -------------------------------------------------------------------------------- /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 | // 変数 a は 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/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/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/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 した値(ニム和)を求める 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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_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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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/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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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/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/chap01/answer_A01.py: -------------------------------------------------------------------------------- 1 | N = int(input()) # 入力 2 | print(N * N) # 出力 3 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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 | # 二次元累積和をとる 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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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/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= 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 | -------------------------------------------------------------------------------- /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_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_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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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/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/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_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 | -------------------------------------------------------------------------------- /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_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 | -------------------------------------------------------------------------------- /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_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/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 | -------------------------------------------------------------------------------- /codes/python/chap05/answer_A33.py: -------------------------------------------------------------------------------- 1 | # 入力 2 | N = int(input()) 3 | A = list(map(int, input().split())) 4 | 5 | # 全部 XOR した値(ニム和)を求める 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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() -------------------------------------------------------------------------------- /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] で取り出せますが、例えば小さいほうから 2 番目の要素が T[1] で取り出せるとは限らないことに注意してください。 -------------------------------------------------------------------------------- /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/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] # 株価はタプルの 2 番目の要素 16 | if kabuka <= A[i]: 17 | level2.pop() 18 | else: 19 | break 20 | if len(level2) >= 1: 21 | answer[i] = level2[-1][0] # 日付はタプルの 1 番目の要素 22 | else: 23 | answer[i] = -1 24 | 25 | # answer を空白区切りで出力 26 | print(*answer) -------------------------------------------------------------------------------- /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) -------------------------------------------------------------------------------- /codes/python/chap09/answer_A62.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | # 再帰呼び出しの深さの上限を 120000 に設定 4 | sys.setrecursionlimit(120000) 5 | 6 | # 深さ優先探索を行う関数(pos は現在位置、visited[x] は頂点 x が青色かどうかを表す真偽値) 7 | def dfs(pos, G, visited): 8 | visited[pos] = True 9 | for i in G[pos]: 10 | if visited[i] == False: 11 | dfs(i, G, visited) 12 | 13 | # 入力 14 | N, M = map(int, input().split()) 15 | edges = [ list(map(int, input().split())) for i in range(M) ] 16 | 17 | # 隣接リストの作成 18 | G = [ list() for i in range(N + 1) ] # G[i] は頂点 i に隣接する頂点のリスト 19 | for a, b in edges: 20 | G[a].append(b) # 頂点 a に隣接する頂点として b を追加 21 | G[b].append(a) # 頂点 b に隣接する頂点として a を追加 22 | 23 | # 深さ優先探索 24 | visited = [ False ] * (N + 1) 25 | dfs(1, G, visited) 26 | 27 | # 連結かどうかの判定(answer = True のとき連結) 28 | answer = True 29 | for i in range(1, N + 1): 30 | if visited[i] == False: 31 | answer = False 32 | 33 | # 答えの出力 34 | if answer == True: 35 | print("The graph is connected.") 36 | else: 37 | print("The graph is not connected.") -------------------------------------------------------------------------------- /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/python/chap09/answer_A65.py: -------------------------------------------------------------------------------- 1 | # 入力(A[2], ..., 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:]) -------------------------------------------------------------------------------- /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) ])) -------------------------------------------------------------------------------- /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)) -------------------------------------------------------------------------------- /codes/python/chap10/answer_A75.py: -------------------------------------------------------------------------------- 1 | # 入力 2 | N = int(input()) 3 | problems = [ list(map(int, input().split())) for i in range(N) ] # タプル (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) -------------------------------------------------------------------------------- /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/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/Editorial_All.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/E869120/kyopro-tessoku/e5062358f013975c5c92885e8474f57f300da6ac/editorial/Editorial_All.pdf -------------------------------------------------------------------------------- /editorial/chap01/chap01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/E869120/kyopro-tessoku/e5062358f013975c5c92885e8474f57f300da6ac/editorial/chap01/chap01.pdf -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/chap01/python/answer_B01.py: -------------------------------------------------------------------------------- 1 | A, B = map(int, input().split()) # 入力 2 | print(A + B) # 出力 3 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /editorial/chap02/chap02.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/E869120/kyopro-tessoku/e5062358f013975c5c92885e8474f57f300da6ac/editorial/chap02/chap02.pdf -------------------------------------------------------------------------------- /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 | // アタリの個数・ハズレの個数の累積和を求める 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 | -------------------------------------------------------------------------------- /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/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 | # アタリについて計算 16 | Atari[i] = Atari[i - 1] 17 | if A[i - 1] == 1: 18 | Atari[i] += 1 19 | # ハズレについて計算 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /editorial/chap03/chap03.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/E869120/kyopro-tessoku/e5062358f013975c5c92885e8474f57f300da6ac/editorial/chap03/chap03.pdf -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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/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/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 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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/answer_B29.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // a の b 乗を m で割った余りを返す関数 5 | // 変数 a は 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 の 2^i 乗」が掛けられるとき 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_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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 した値(ニム和)を求める 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/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 した値(ニム和)を求める 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/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 | -------------------------------------------------------------------------------- /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 数 9 | XOR_Sum ^= Grundy[A[i] % 5] 10 | 11 | # 出力 12 | if XOR_Sum != 0: 13 | print("First") 14 | else: 15 | print("Second") 16 | -------------------------------------------------------------------------------- /editorial/chap05/chap05.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/E869120/kyopro-tessoku/e5062358f013975c5c92885e8474f57f300da6ac/editorial/chap05/chap05.pdf -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/cpp/answer_B29.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // a の b 乗を m で割った余りを返す関数 5 | // 変数 a は 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 の 2^i 乗」が掛けられるとき 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 した値(ニム和)を求める 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/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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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 した値(ニム和)を求める 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_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 数 9 | XOR_Sum ^= Grundy[A[i] % 5] 10 | 11 | # 出力 12 | if XOR_Sum != 0: 13 | print("First") 14 | else: 15 | print("Second") 16 | -------------------------------------------------------------------------------- /editorial/chap06/chap06.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/E869120/kyopro-tessoku/e5062358f013975c5c92885e8474f57f300da6ac/editorial/chap06/chap06.pdf -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /editorial/chap08/chap08.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/E869120/kyopro-tessoku/e5062358f013975c5c92885e8474f57f300da6ac/editorial/chap08/chap08.pdf -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /editorial/chap09/chap09.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/E869120/kyopro-tessoku/e5062358f013975c5c92885e8474f57f300da6ac/editorial/chap09/chap09.pdf -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | # Python では多次元配列は 1 次元に flatten した方が速い (ここでは使わない) 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 | -------------------------------------------------------------------------------- /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 # 同じ頂点から複数回探索しない (worst Θ(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) -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /editorial/chap09/python/answer_B67.py: -------------------------------------------------------------------------------- 1 | N, M = map(int, input().split()) 2 | 3 | edge = [] 4 | for _ in range(M): 5 | A, B, C = map(int, input().split()) 6 | A -= 1 7 | B -= 1 8 | edge.append((A, B, C)) 9 | 10 | # 長さの逆順でソート 11 | edge.sort(key=lambda e: -e[2]) 12 | 13 | # union-find 14 | uf = [-1] * N 15 | def root(i: int) -> 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/final/cpp/answer_C03.cpp: -------------------------------------------------------------------------------- 1 | #include 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /editorial/final/final_01-10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/E869120/kyopro-tessoku/e5062358f013975c5c92885e8474f57f300da6ac/editorial/final/final_01-10.pdf -------------------------------------------------------------------------------- /editorial/final/final_11-20.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/E869120/kyopro-tessoku/e5062358f013975c5c92885e8474f57f300da6ac/editorial/final/final_11-20.pdf -------------------------------------------------------------------------------- /errata/errata_editorialPDF.md: -------------------------------------------------------------------------------- 1 | ## 正誤表(解説 PDF) 2 | 最終更新日は 2023/7/21 です。 3 | 4 | | **該当ページ** | **該当箇所** | **誤** | **正** | **備考** | 5 | |:---|:---|:---|:---|:---| 6 | | p.31 | 11 行目 | Q = [0, 38, 45, 50, 83, 88, 95, 131] | Q = [0, 38, 45, 50, 83, 88, 95, 133] | - | 7 | | p.39 | 具体例 1 行目 | N=5,S=5,A=[2,2,3] | N=3,S=5,A=[2,2,3] | - | 8 | | p.47 | 脚注 5 | 3 文字目の「k」を追加すると | 3 文字目の「z」を追加すると | - | 9 | | p.48 | 下から 7 行目 | S[l]=T[t] の場合 | S[l]=S[r] の場合 | - | 10 | | p.48 | 下から 5 行目 | S[l]≠T[t] の場合 | S[l]≠S[r] の場合 | - | 11 | | p.69 | タイトルの問題名 | B33:Game 6 | B34:Game 7 | - | 12 | | p.75 | 一般のケースで R[i][j] を求める | R[0][0]=R[0][1]=80,R[0][2]=74,R[0][3]~R[0][9]=70 | R[1][0]=R[1][1]=80,R[1][2]=74,R[1][3]~R[1][9]=70 | - | 13 | | p.113 | 1 つ目のソースコード 19 行目 | dp[posL] から dp[posR] までの最大値 | dp[posL] から dp[posR] までの最小値 | - | 14 | | p.113 | 動的計画法の高速化の 2, 5 行目 | 区間の最大値 | 区間の最小値 | - | 15 | | p.197 | 初期状態 | dp[1][2]=...=dp[2×N-1][2×N]=0 | dp[1][2]=...=dp[2xN-1][2×N]=abs(A[2×i-1]-A[2×i]) | - | 16 | --------------------------------------------------------------------------------