【AtCoder】ABC 444 C - AtCoder Riko

実行時間制限: 2 sec / メモリ制限: 1024 MiB / Difficulty: 582 / NoviSteps: ??? / 配点: 350 点
問題概要
長さ の正整数列 が与えられる。 以下のようなことが起こりうる正整数 をすべて求めよ。
カップの中に長さ のAtCoderりこが何本か入っている。 高橋君がこのカップをシェイクしたところ、それぞれのAtCoderりこは以下のいずれかの状態になった。
- 長さが である 本のAtCoderりことしてそのまま残った。
- 長さの和が であるような 本のAtCoderりこに分かれた。ただし、各 AtCoderりこの長さは正整数である。
カップをシェイクした後、カップの中には 本のAtCoderりこが入っており、 本目の AtCoderりこの長さは であった。
制約
- 条件を満たすような が少なくとも つ存在する
- 入力される値は全て整数
考察
シェイクすることで折れたAtCoderりこは、長さとしては短くなるので、 の要素の中で小さいものになるはず。
したがって、 を昇順ソートすることによって、折れたAtCoderりこは前方に、 折れていないAtCoderりこは後方にまとまることが期待できる。
折れたAtCoderりこの本数を とすると( は偶数)、 の最初の 本が折れたAtCoderりこ、 残りの 本が折れていないAtCoderりことなる。
(折れたAtCoderりこが 本) の場合
このとき、全てのAtCoderりこは長さ のままであるはずである。
はソートされているはずなので、 と が等しければ、 が成立する。
(折れたAtCoderりこが 本以上) の場合
が候補となる。
のとき、折れていないAtCoderりこが存在し、その長さは と等しくなければならない。 これは先ほどと同様に、 と が と等しいかどうかを確認することで判定できる。
さらに、折れたAtCoderりこが 本あるとき、 番目に短いAtCoderりこと 番目に短い(折れた 本の中で 番目に長い)AtCoderりこがペアになって長さ になるはずである。
したがって、 について、 であるかどうかを確認すればよい。
これらの条件を満たす は本問の答えとして成立する。
答えとなる は複数存在する可能性があるため、setなどを用いて重複を排除しつつ格納しておくとよい。
実装例
実装は0-indexedで行っていることに注意。
1.#include <bits/stdc++.h>2.using namespace std;3. 4.#define all(x) (x).begin(), (x).end()5.#define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++)6. 7.using ll = long long;8. 9.// ======================================== //10. 11.int main()12.{13. int N;14. cin >> N;15. vector<ll> A(N);16. rep(i, 0, N) cin >> A[i];17. 18. sort(all(A));19. 20. set<ll> ans;21. 22. if (A[0] == A[N - 1])23. ans.insert(A[0]);24. 25. for (int m = 2; m <= N; m += 2)26. {27. ll L = A[0] + A[m - 1];28. if (m < N)29. {30. if (A[m] != L || A[N - 1] != L)31. continue;32. }33. 34. bool flag = true;35. rep(i, 1, m / 2)36. {37. if (A[i] + A[m - 1 - i] != L)38. {39. flag = false;40. break;41. }42. }43. 44. if (flag)45. ans.insert(L);46. }47. 48. for (auto &&x : ans)49. {50. cout << x << " ";51. }52. cout << endl;53. 54. return 0;55.}実装時間: 25分
コメント
AtCoderりこ、ネーミングもうちょっと何とかならんかったんか??? 言いにくすぎだろ。





