ABC336
概要
実力的には二年前に茶色になって放置して暫くぶりの参加なので詳しい解説などは期待しないでもらえると。
同じぐらいの初心者さんがこんな感じで解いたのかぁ的な見方か、上級者の方が愉悦として見ていただけると幸いです。
A - Long Loong
考えてたこと
特になし
提出したもの
int main() {
int n;
cin >> n;
string ans;
ans += "L";
rep(i, 0, n) {
ans += "o";
}
ans += "ng";
cout << ans << endl;
return 0;
}
振り返り
特になし
B - CTZ
考えてたこと
10進数の数字をn進数に直すみたいなの、高校の時やった覚えがあります。
2で割っていってどこまで余りが出ないか数えるだけ。
提出したもの
int main() {
int n;
cin >> n;
int ans = 0;
while (true) {
if (n % 2 == 0) {
ans++;
n /= 2;
} else
break;
}
cout << ans << endl;
return 0;
}
振り返り
bitを用いるやり方や、countr_zero
を用いるやり方など解説から勉強。
C - Even Digits
考えてたこと
出力例の値がかなり大きかったから普通に解く問題じゃないだろうなぁと予想。
B問題でやったみたいにn進数の余りをうまく使ったら解けそうと判断。
先に良い整数を小さい順に配列で持っておいてn進数の余りをkeyとして持ってきてそれを1の位から並べていく、それだけ。
提出したもの
int main() {
ll num;
cin >> num;
num--;
ll ans = 0;
int goodNum[] = {0, 2, 4, 6, 8};
ll numTimes = 1;
while (num > 0) {
ll a = num % 5;
ans += goodNum[a] * numTimes;
num /= 5;
numTimes *= 10;
}
cout << ans << endl;
return 0;
}
振り返り
実際に掛け算をして値を求めてたけど、回答を見てそもそも計算する必要もないと気づきました。文字列として小さい桁から順に数字を持って最後にreverse
するやり方の方が桁の値が大きくても良いし計算もしなくて安全。問題作成者の性格次第でLLでも回答範囲外に出来るから正直危なかったかも、反省。
D - Pyramid
考えてたこと
全然わかりませんでした。
解答読んだらかなり純粋な算数?数学?でびっくりしました。
youtubeの公式解説のdr[i]=min(dr[i+1]+1,vec)
みたいな解き方が好きで解説を聞いている途中で一回自分で書いてみたらACしました。
提出したもの
int main() {
int n;
cin >> n;
vector<int> vec(n);
rep(i, 0, n) cin >> vec[i];
vector<int> max_left(n);
vector<int> max_right(n);
for (int i = 0; i < n; i++) {
if (i == 0) {
max_left[i] = 1;
} else {
max_left[i] = min(max_left[i - 1] + 1, vec[i]);
}
}
for (int i = n - 1; 0 <= i; i--) {
if (i == n - 1) {
max_right[i] = 1;
} else {
max_right[i] = min(max_right[i + 1] + 1, vec[i]);
}
}
int ans = 0;
for (int i = 0; i < n; i++) {
int now_ans = min(max_left[i], max_right[i]);
ans = max(ans, now_ans);
}
cout << ans << endl;
return 0;
}
振り返り
パワーで解くやり方なら気づけたかもだから反省、諦めずに。
感想
D問題でかなり詰まってたので、解説を見たら楽しくなってモチベがちょっと復活してきました。わくわくです。