AtCoder Beginner Contest 302 感想 A問題 B問題
総評
いぇい、いぇい!
— アシツノカラ (@ashitsunokara) 2023年5月20日
ashitsunokaraさんのトヨタ自動車プログラミングコンテスト2023#2(AtCoder Beginner Contest 302)での成績:1958位
パフォーマンス:1082相当
レーティング:919→936 (+17) :)#AtCoder #トヨタ自動車プログラミングコンテスト2023#2(ABC302) https://t.co/oSUdiRKaqj pic.twitter.com/s2kkC5m4Ua
AtCoder Beginner Contest(ABC)に参加してきました!
結果はAとBとCとDとEの5つACして5完でした。
やった!
参加する前に4完か5完したいって言っていたので言った通り実現できてうれしいです!
パフォーマンスも1000を越えて満足いってます。
やった、やった!
昨日のことですけど、もうすごくうれしいです!
やった!
今回は配点がいつもと変わっていました。
B問題とC問題が250点でいつもはB問題が200点、C問題が300点で「どんな風になるんだろ……?」と思っていました。
蓋を開けてみればB問題がいつもに比べると本当に250点相当に難しい!
これで苦戦した人いるんじゃないかなと思います。
私もまあまあ解くのに時間かかりました。
問題 | A | B | C | D | E | F | G | Ex |
---|---|---|---|---|---|---|---|---|
配点 | 100 | 250 | 250 | 400 | 425 | 500 | 625 | 625 |
私の実力的にAからE問題を解いて5完というのは終わってみれば妥当だと思います。
F問題はちょっと難しかった……!
時間があっても解けなかったと思います。
なので、満足です。
欲張りすぎず、自分の実力に合った成績が出ているのでまあまあ、よし!
良かった、良かった!
そんな感じで捉えてます。
この記事は感想なので、解説書いたり書かなかったりです。
解説書いているといつまでも時間がかかって書ききれないので、あまり書かないと思います。
そんなわけで一問一問振り返っていきます。
コードも載せたり載せなかったりです。
適当にやっていきましょう。
A - Attack
A問題は次のようなコードで解きました。
数学です。
数学の式です。
これは知っているか否かなので、知らなかった方は公式の解説を読むといいと思います。
切り上げのテクニックなので「割り算 切り上げ プログラミング」くらいで検索したら出てこないかな?
#include <bits/stdc++.h> using namespace std; int main() { ios_base::sync_with_stdio(false); cin.tie(0); long long A, B; cin >> A >> B; cout << (A + B - 1) / B << endl; return 0; }
場合分けで解いても良かったですね!
むしろそっちの方が早く解けたかもしれない!
「えっと、切り上げのときの式ってどう書くんだっけ」と考えていたら遅れたので……。
A問題で出遅れるなんてなさけないです。
しかし、私は結構解くの遅い方で、いつもA問題解くのに時間がかかって……お気に入りに入れている人たちと比べて「遅い……なんて遅いんだ!」になってます。
場合分け無しだと、次のような感じですね。
今さっと書けたんで、そっちの方が良かったかなあ? になってます。
A問題に2分くらいかかっていて、たぶんこっちの解法だともう少し早く解けた……!?
まあ、あまり変わらないので気にしてません。
どっちだって正解ですし、序盤の早さは気にしません。
#include <bits/stdc++.h> using namespace std; int main() { ios_base::sync_with_stdio(false); cin.tie(0); long long A, B; cin >> A >> B; if (A % B == 0LL) { cout << A / B << endl; } else { cout << A / B + 1 << endl; } return 0; }
B - Find snuke
この問題は難しかったですね……、B問題なのに!
ただ、やったことある解法だったのに、私はサクサク書いていけました。
それでも解くのに10分くらいかかってますが……!
たしか、解いたときはpredictorで1200のパフォーマンスを越えていたような気がします。
みんな苦戦していたようです。
確かに時間かかっても解けなかった人がいると思います。
今回A問題しか解けなかった人も心配することはないです。
私もABCで1完だったときにかなり苦しんで「才能ないのかな?」とかいろいろ頭によぎりました。
ABC、1完はしんどい、辛い気分になりますが、気にすることないです。
誰でも起こりうることだし、自分の能力を信じてあげた方が絶対にいいです。
#include <bits/stdc++.h> using namespace std; int main() { ios_base::sync_with_stdio(false); cin.tie(0); long long H, W; cin >> H >> W; vector<string> S(H, ""); for (long long i = 0LL; i < H; ++i) { cin >> S[i]; } string snuke = "snuke"; vector<pair<long long, long long>> dxdy { {0, 1}, {1, 0}, {0, -1}, {-1, 0}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1} }; for (long long i = 0LL; i < H; ++i) { for (long long j = 0LL; j < W; ++j) { for (auto &[dy, dx] : dxdy) { vector<pair<long long, long long>> ans; bool flag = true; for (long long k = 0LL; k < 5; ++k) { long long ny = i + dy * k; long long nx = j + dx * k; if (ny >= 0LL && ny < H && nx >= 0LL && nx < W && S[ny][nx] == snuke[k]) { ans.push_back(make_pair(ny, nx)); } else { flag = false; break; } } if (flag) { for (auto &[a, b] : ans) { cout << a + 1 << " " << b + 1 << endl; } return 0; } } } } return 0; }
この問題には定石があり、私の書いたコードの中ではdxdy(ディーエックスディーワイ)と書かれているところです。
これを用いて8方向に探索します。
for文で8方向に動かせるので、if文をいっぱい書くよりも楽です。
私はこの方法を競技プログラミングをするまで知りませんでした。
競技プログラミング以外で使ったことあるかと言われるとないですが……すごく便利です。
頭いいなと思います。
#include <bits/stdc++.h> using namespace std; int main() { vector<pair<long long, long long>> dxdy { {0, 1}, {1, 0}, {0, -1}, {-1, 0}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1} }; for (auto &[dy, dx] : dxdy) { cout << dy << " " << dx << endl; } return 0; }
とりあえずこれで8方向にイチマスずつ探索出来ます。
今回は縦横斜めに5マス連続で見ないといけないので少し工夫が要ります。
ついでなので説明します。
私ので分からなかったら、他の人のコードを見るといいと思います……それくらい便利なので覚えておいた方がのちのちの競技プログラミングの問題でも楽をすることができると思うので、分かっておいた方がいいと思います。
次に書く2つのコードの内どちらでも8方向で5マス連続で走査していることが分かると思います。
少し工夫が要ります。
難しいですが、覚えておいて損はないです!
ABCでもときどきこういうことができると得をすることがあるので覚えておくといいでしょう……さっきも言ったかな?
まあ、いいや。
自分で書いていて勉強になりました。
#include <bits/stdc++.h> using namespace std; int main() { vector<pair<long long, long long>> dxdy { {0, 1}, {1, 0}, {0, -1}, {-1, 0}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1} }; long long i = 0LL; long long j = 0LL; for (auto &[dy, dx] : dxdy) { for (long long k = 0LL; k < 5; ++k) { long long ny = i + dy * k; long long nx = j + dx * k; cout << ny << " " << nx << endl; } cout << endl; } return 0; }
#include <bits/stdc++.h> using namespace std; int main() { vector<pair<long long, long long>> dxdy { {0, 1}, {1, 0}, {0, -1}, {-1, 0}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1} }; long long i = 0LL; long long j = 0LL; for (auto &[dy, dx] : dxdy) { long long ny = i; long long nx = j; for (long long k = 0LL; k < 5; ++k) { cout << ny << " " << nx << endl; ny += dy; nx += dx; } cout << endl; } return 0; }
終わり
長くなったのと夜も遅くなったので今日は一旦ここで区切ります。
続きは書くかもしれないし、書かないかもしれません。
振り返りしながら他人のコードを見たり、考えたり、まとめたりすると頭が良くなる感じが……やっていて意味があります。
楽しいのでするかもしれません。