AtCoder Beginner Contest 126[ABC126]の復習
いまさらながらふくしゅー
A - Changing a Character
小文字を大文字にする。大文字小文字は32離れている。
Asciiコード調べるのに時間かかった。
#include <iostream> #include <string> int main() { int N, K; std::string S; std::cin >> N >> K; std::cin >> S; S[K - 1] += 32; std::cout << S << std::endl; }
B - YYMM or MMYY
12がどうなっているか判定するだけ。'0'は48だよ。 Ascii調べたから文字→数字は計算で。
#include <iostream> #include <string> int main() { std::string S; std::cin >> S; int prev = (S[0] - 48) * 10 + (S[1] - 48); int next = (S[2] - 48) * 10 + (S[3] - 48); bool prev_flag = false; bool next_flag = false; if ((0 < prev) && (prev < 13)) { prev_flag = true; } if ((0 < next) && (next < 13)) { next_flag = true; } std::string result; if (prev_flag & next_flag) { result = "AMBIGUOUS"; } else if (prev_flag) { result = "MMYY"; } else if (next_flag) { result = "YYMM"; } else { result = "NA"; } std::cout << result << std::endl; }
C - Dice and Coin
すごく初手で決まるゲームだなと思った(こなみ
while (v <= K) {
って書いててテストケースが合致しない?なんで?ってなって辛かった。 出力printfで書けばsetprecisionとかしなくていいのにね。
#include <iomanip> #include <iostream> int main() { int N, K; std::cin >> N >> K; double over_K = 0.0; double sum = 0.0; for (int i = 1; i <= N; ++i) { int v = i; double prov = 1.0; while (v < K) { prov *= 0.5; v *= 2; } sum += prov; } double result = sum / N; std::cout << std::setprecision(20) << result << std::endl; return 0; }
D - Even Relation
解説読んでも問題文の意味が分からない。なんで。
当日は意味が分からない???でタイムアップ。Eやればよかったのにね。
E - 1 or 2
異世界転生してカードに書かれた整数を知ることができるのでゴリゴリと書くだけ。
最初LUTで解こうとしたけど大変だったので、適当に書いた。 これグラフで連結数っていうのかって解説見て思った。
queue使ったほうが実装楽だけど、vectorでごり押したほうがpop無い分速そう。 hintのclearはおまけ。やる必要ないしやるだけ遅くなるよ(多分
#include <iostream> #include <queue> #include <vector> int main() { int N, M; std::cin >> N >> M; std::vector<std::vector<int>> hint(N); std::vector<int> lut(N); for (int i = 0; i < M; ++i) { int x, y, z; std::cin >> x >> y >> z; hint[x - 1].push_back(y - 1); hint[y - 1].push_back(x - 1); } std::vector<int> chain; int num = 0; for (int i = 0; i < N; ++i) { int table; if (lut[i] == 0) { ++num; lut[i] = num; chain.clear(); } else { continue; } chain.push_back(i); for (int i = 0; i < chain.size(); ++i) { auto c = chain[i]; for (auto &h : hint[c]) { if (lut[h] == 0) { lut[h] = num; chain.push_back(h); } } hint[c].clear(); } } int result = num; std::cout << result << std::endl; return 0; }
F - XOR Matching
M=2とM=3の時にどうすればいいのか、紙に書いてたら真ん中と端に目的の値おいて、あとは他の値でサンドイッチすればいいことに気付いた。
M=2、K=1なら、1 0 2 3 1 3 2 0
1と1の間は0 xor 2 xor 3=1になる。
0と0の間は2 xor 3 xor 1 xor 3 xor 2=1になる。
2のM乗未満の値を1つずつ取り出して排他的論理和を取ると、M=2の場合は0 xor 1 xor 2 xor 3=0、という感じで0になるので、そこから目的の値を引っこ抜いて端と中央に配置すればOK。 もちろん2のM乗<=Kの時点で解けない。
例示は理解の試金石。
例外ケースが入力例にあったので例外ケースはスムーズに書けた。
出力でstringstream使ったほうがいいかなと思ったけど、とりあえず書いたら通ったのであまり気にしないことにした。
#include <cmath> #include <iostream> #include <vector> int main() { int M, K; std::cin >> M >> K; int max = 1 << M; std::vector<int> result(max * 2); if (max <= K) { std::cout << -1 << std::endl; return 0; } if (M == 0) { if (K == 1) { std::cout << -1 << std::endl; return 0; } else { result[0] = 0; result[1] = 0; } } else if (M == 1) { if (K == 1) { std::cout << -1 << std::endl; return 0; } else { result[0] = 0; result[1] = 0; result[2] = 1; result[3] = 1; } } else { // 最初と真ん中らへんにKを配置する result[0] = result[max] = K; int val = 0; for (int i = 1; i < max; ++i) { if (val == K) { ++val; } result[i] = result[result.size() - i] = val; ++val; } } for (auto r : result) { std::cout << r << " "; } std::cout << std::endl; }