全体
55分(1WA)で全完の222位。D問題が解けなさ過ぎて気持ちは冷えていたし身体は熱くなっていた。400点問題がまさか解けない……!? みたいなプレッシャーのかかり方ほんと厳しい。
A問題
double
を表示するときはprintf
を使ってしまうね。
#include"bits/stdc++.h" using namespace std; using ll = int64_t; int main() { double T, X; cin >> T >> X; printf("%.10f\n", T / X); }
B問題
accumulate
とかmax_element
とかを使いたがる。
#include"bits/stdc++.h" using namespace std; using ll = int64_t; int main() { ll N; cin >> N; vector<ll> L(N); for (ll i = 0; i < N; i++) { cin >> L[i]; } ll sum = accumulate(L.begin(), L.end(), (ll)0); ll max = *max_element(L.begin(), L.end()); cout << (max < (sum - max) ? "Yes" : "No") << endl; }
C問題
最初は個の駒を全部端から置いていっていいのかなと思ったけど、中央に密集していて両端二つだけめちゃくちゃ離れているときにどっち端から置いていってもダメだということを考えて、じゃあ隣との差が大きいところから置いておくんだということになり、差分を取ってそれの小さい方から個の和が答えということで出す、通る。今気づいたけどこういうところこそaccumulate
の使いどころなんじゃないか。なんにしてもここまでは順調だったのに……。
#include"bits/stdc++.h" using namespace std; using ll = int64_t; int main() { ll N, M; cin >> N >> M; vector<ll> X(M); for (ll i = 0; i < M; i++) { cin >> X[i]; } if (N >= M) { cout << 0 << endl; return 0; } sort(X.begin(), X.end()); vector<ll> diff; for (ll i = 1; i < M; i++) { diff.push_back(X[i] - X[i - 1]); } sort(diff.begin(), diff.end()); ll ans = 0; for (ll i = 0; i < M - N; i++) { ans += diff[i]; } cout << ans << endl; }
D問題
本日の問題児。全然解けなくてめちゃくちゃ焦った。最初は両辺で排他的論理和を取れば右辺のが全部消えるんじゃねとか考えていたけどそんなことはない。よくわからないので実験してみるがあまり法則性も見つからない。困った困ったと悩んでいると「排他的論理和は桁ごとに見る」という定跡を思い出す。そうやって考えていくとを各桁で串刺しして見て、0が多い桁はを1にしたいし、1が多い桁はその逆ということに気づく。ここまでで30分くらいかかった。
実装でも時間がかかる。2進数にするには文字列にすればいいとかいう謎の勘違いをしたり、の範囲制限をすっかり忘れていたり、繰り上がりを2進数として実装しようとして悩んだり、ひどかった。最近あまり競技プログラミングをやっていないもので、実装はすぐに腕が落ちる。実装した後もなんか1WAが出てしまい、よくわからないけど方針は合っている気がしたのでリファクタリングしてコードを奇麗にしたら通った。ビットシフトのどこかだと思う。ビットシフトはバグを生みがち。
ここで恐ろしい話。
D問題、これの答え17だよね?最初にACを取ったコードは16を返す。
— merom686 (@merom686) 2019年2月3日
3 6
2 0 0
僕のも16が出るので嘘です。そうか、ちゃんとbitDPをやる方がまともだったかもしれないんですね。うーん、なぜbitDPの発想が出てこないのか。ガタガタだなぁ。まぁこういうこともあると切り替えていきましょう。
#include"bits/stdc++.h" using namespace std; using ll = int64_t; ll N, K; vector<ll> A; int main() { cin >> N >> K; A.resize(N); for (ll i = 0; i < N; i++) { cin >> A[i]; } ll ans = 0; bool under = false; for (ll i = 63; i >= 0; i--) { ll num1 = 0; for (ll j = 0; j < N; j++) { num1 += (A[j] & (1LL << i)) != 0; } if (!under && ((K & (1LL << i)) == 0)) { //0しか選べない } else { if (num1 >= N - num1) { //0を選んだ方が良い under = true; } else { //1を選んだ方が良い num1 = N - num1; } } ans += num1 * (1LL << i); } cout << ans << endl; }