C++の練習を兼ねて, AtCoder Beginner Contest 275 の 問題C (Counting Squares) ~ 問題D (Yet Another Recursive Function) を解いてみた.
■感想.
1. 問題C, D は, 方針を絞り込めたので, AC版に到達できたと思う.
2. 個人的には, 問題D で, メモ化再帰の復習が出来たので, 非常に良かったと思う.
3. 引き続き, 時間を見つけて, 過去問の学習を進めていきたいと思う.
本家のサイト AtCoder Beginner Contest 275 解説 の 各リンク を ご覧下さい.
■C++版プログラム(問題C/AC版).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
// C++(GCC 9.2.1) #include <bits/stdc++.h> using namespace std; using P = pair<int, int>; using vp = vector<P>; #define repex(i, a, b, c) for(int i = a; i < b; i += c) #define repx(i, a, b) repex(i, a, b, 1) #define rep(i, n) repx(i, 0, n) #define repr(i, a, b) for(int i = a; i >= b; i--) #define a first #define b second #define pb push_back int main(){ // 1. 入力情報. vp o; rep(i, 9){ char c[22]; scanf("%s", c); rep(j, 9) if(c[j] == '#') o.pb({i, j}); } // 2. ポーンが, 4頂点に置いてある正方形の個数は? int ans = 0, n = o.size(); rep(v1, n){ rep(v2, n){ int x12 = o[v1].a - o[v2].a; int y12 = o[v1].b - o[v2].b; rep(v3, n){ int x23 = o[v2].a - o[v3].a; int y23 = o[v2].b - o[v3].b; rep(v4, n){ int x34 = o[v3].a - o[v4].a; int y34 = o[v3].b - o[v4].b; int x41 = o[v4].a - o[v1].a; int y41 = o[v4].b - o[v1].b; // 4頂点でない. if(v1 == v2 || v2 == v3 || v3 == v4 || v4 == v1) continue; // 辺の長さが, すべて等しいか? int d12 = x12 * x12 + y12 * y12; int d23 = x23 * x23 + y23 * y23; int d34 = x34 * x34 + y34 * y34; int d41 = x41 * x41 + y41 * y41; if(!(d12 == d23 && d23 == d34 && d34 == d41)) continue; // 共通の頂点を持つ二辺のなす角が, 90度か? int a123 = x12 * x23 + y12 * y23; int a234 = x23 * x34 + y23 * y34; int a341 = x34 * x41 + y34 * y41; int a412 = x41 * x12 + y41 * y12; if(a123 != 0 || a234 != 0 || a341 != 0 || a412 != 0) continue; // カウント. ++ans; } } } } // 3. 出力. printf("%d\n", ans / 8); return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
[入力例] ##....... ##....... ......... .......#. .....#... ........# ......#.. ......... ......... [出力例] 2 ※AtCoderテストケースより [入力例] .#....... #.#...... .#....... ......... ....#.#.# ......... ....#.#.# ........# ......... [出力例] 3 ※AtCoderテストケースより [入力例] ....####. ..#.##.#. #.##....# .###.#..# ....#.#.. .......#. .#..##... ..#.#.#.# #..##.#.# [出力例] 8 [入力例] #.#...##. #.#.##.## .##...... #..#.##.# .####.#.# .#..###.. .#..##.## #.####.## ##..#.... [出力例] 31 [入力例] ####.#### ###.#.### ##.###.## #.#####.# .#######. #.#####.# ##.###.## ###.#.### ####.#### [出力例] 252 |
■C++版プログラム(問題D/AC版).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// C++(GCC 9.2.1) #include <bits/stdc++.h> using namespace std; using LL = long long; int main(){ // 1. 入力情報. LL N; scanf("%lld", &N); // 2. dfs. // https://ja.wikipedia.org/wiki/深さ優先探索 map<LL, LL> memo; auto dfs = [&](auto&& self, LL k) -> LL { // 2-1. 終了条件. if(memo.count(k)) return memo[k]; if(k == 0) return memo[0] = 1; // 2-2. メモ化. return (memo[k / 2] = self(self, k / 2)) + (memo[k / 3] = self(self, k / 3)); }; // 3. 出力. printf("%lld\n", dfs(dfs, N)); return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
[入力例] 2 [出力例] 3 ※AtCoderテストケースより [入力例] 0 [出力例] 1 ※AtCoderテストケースより [入力例] 100 [出力例] 55 ※AtCoderテストケースより [入力例] 2023 [出力例] 615 [入力例] 20230205 [出力例] 888145 [入力例] 202210292100 [出力例] 1160445931 [入力例] 1000000000000000000 [出力例] 224412958156019 |
■参照サイト
AtCoder Beginner Contest 275