AtCoder Beginner Contest 112に参加しました
AtCoder Beginner Contest 112に参加したので記録を残したいと思います.
問題のタイトルは以下のようになっています.
- A - Programming Education
- B - Time Limit Exceeded
- C - Pyramid
- D - Partition
A - Programming Education
問題の概要
入力がならば'Hello World'を出力し、
ならば更に整数の入力
を受け取り、
の結果を出力する.
解法
のときと
のときで条件分岐してあげます.
最初に整数を受け取るのではなく、
のときにのみ入力を受け取るように気をつけます.
#include <iostream> #include <string> #include <vector> #include <cstdlib> #include <cstdio> #include <cmath> #include <algorithm> #include <map> #include <stack> #include <queue> #include <set> #include <cstring> using namespace std; // ascending order #define vsort(v) sort(v.begin(), v.end()) // descending order #define vsort_r(v) sort(v.begin(), v.end(), greater<int>()) #define vunique(v) unique(v.begin(), v.end()) #define mp make_pair #define ts(x) to_string(x) #define rep(i, a, b) for(int i = (int)a; i < (int)b; i++) #define repm(i, a, b) for(int i = (int)a; i > (int)b; i--) #define bit(a) bitset<8>(a) #define des_priority_queue priority_queue<int, vector<int>, greater<int> > #define all(v) (v).begin(), (v).end() typedef long long ll; typedef pair<int, int> P; const ll INF = 1e18; int main(){ cin.tie(0); ios::sync_with_stdio(false); int N; cin >> N; if(N == 1) { cout << "Hello World" << endl; } else { int A, B; cin >> A >> B; cout << A + B << endl; } }
B - Time Limit Exceeded
問題の概要
個の経路のなかで、時間
以内に帰宅できる経路のうちコストが最小となる経路のコストを出力する.
ただし、番目の経路はコスト
かけて時間
で帰宅できる.
解法
全探索します. 時間以下の
に対応するコスト
の中で最小のものを出力することで目的を果たせます.
#include <iostream> #include <string> #include <vector> #include <cstdlib> #include <cstdio> #include <cmath> #include <algorithm> #include <map> #include <stack> #include <queue> #include <set> #include <cstring> using namespace std; // ascending order #define vsort(v) sort(v.begin(), v.end()) // descending order #define vsort_r(v) sort(v.begin(), v.end(), greater<int>()) #define vunique(v) unique(v.begin(), v.end()) #define mp make_pair #define ts(x) to_string(x) #define rep(i, a, b) for(int i = (int)a; i < (int)b; i++) #define repm(i, a, b) for(int i = (int)a; i > (int)b; i--) #define bit(a) bitset<8>(a) #define des_priority_queue priority_queue<int, vector<int>, greater<int> > #define all(v) (v).begin(), (v).end() typedef long long ll; typedef pair<int, int> P; const ll INF = 1e18; int main(){ cin.tie(0); ios::sync_with_stdio(false); int N, T; cin >> N >> T; vector<int> c, t; rep(i, 0, N) { int tmp_c, tmp_t; cin >> tmp_c >> tmp_t; c.push_back(tmp_c); t.push_back(tmp_t); } int rsl = 1e9; rep(i, 0, N) { if(t[i] <= T) rsl = min(rsl, c[i]); } if(rsl == 1e9) cout << "TLE" << endl; else cout << rsl << endl; }
C - Pyramid
問題の概要
ピラミッドには中心座標と高さ
が定まっている. 座標
の高度は
である.
の高度は
であるという情報が
個与えられるので、その情報をもとに中心座標と高さを求める.
解法
最初はなんのこっちゃ分からなかったのですが、入力例2のが0以上100以下の整数であるとわかっていることに注意せよ.という一文を見て閃きました.
と
が100以下の整数ならそれらに対して全探索しちゃえば良いのでは?と考えました. (制約を見た時点で思いつくべきでしたが、なぜかこの一文を見た時に解法を思いつきました.)
そうすると、残るをどうするかが問題になってきます. 残る
を定めてしまえば、適当に定めた
を用いて
個の情報に矛盾しないか一つずつ試していけば良いことになります.
の定め方は
が0のときとそうでないときで場合分けしました.
が0でないとき
という定義より、ある中心座標の候補である
を用いて、
が成り立ちます. したがって、
となります.
これで、ある
に対する
を一つ定めることができました. この
を用いたとき全ての情報に矛盾が生じなかったとき、その
が答えとなります.
が0のとき
が0のときは、
となります. したがって、
の値は、
に絞ることができます. したがってこの範囲の中で情報に矛盾の生じない
が存在すれば、その
が答えとなります.
#include <iostream> #include <string> #include <vector> #include <cstdlib> #include <cstdio> #include <cmath> #include <algorithm> #include <map> #include <stack> #include <queue> #include <set> #include <cstring> using namespace std; // ascending order #define vsort(v) sort(v.begin(), v.end()) // descending order #define vsort_r(v) sort(v.begin(), v.end(), greater<int>()) #define vunique(v) unique(v.begin(), v.end()) #define mp make_pair #define ts(x) to_string(x) #define rep(i, a, b) for(int i = (int)a; i < (int)b; i++) #define repm(i, a, b) for(int i = (int)a; i > (int)b; i--) #define bit(a) bitset<8>(a) #define des_priority_queue priority_queue<int, vector<int>, greater<int> > #define all(v) (v).begin(), (v).end() typedef long long ll; typedef pair<int, int> P; const ll INF = 1e18; int main(){ cin.tie(0); ios::sync_with_stdio(false); int N; cin >> N; vector<int> x, y, h; rep(i, 0, N) { int tmp_x, tmp_y, tmp_h; cin >> tmp_x >> tmp_y >> tmp_h; x.push_back(tmp_x); y.push_back(tmp_y); h.push_back(tmp_h); } rep(xi, 0, 101) rep(yi, 0, 101) { if(h[0] != 0) { int H = h[0] + abs(x[0] - xi) + abs(y[0] - yi); bool flag = true; rep(i, 0, N) { if(h[i] != max(H - abs(x[i] - xi) - abs(y[i] - yi), 0)) { flag = false; break; } } if(flag) { cout << xi << " " << yi << " " << H << endl; return 0; } } else { int max_h = abs(x[0] - xi) + abs(y[0] - yi); rep(hi, 0, max_h + 1) { bool flag = true; rep(i, 0, N) { if(h[i] != max(hi - abs(x[i] - xi) - abs(y[i] - yi), 0)) { flag = false; break; } } if(flag) { cout << xi << " " << yi << " " << hi << endl; } } } } }
D - Partition
問題の概要
整数が与えられる.
となる整数からなる長さ
の数列
において、
の最大公約数の取り得る最大値を求める.
解法
整数問題苦手ですね... またしても時間内に解けませんでした.
例えば数列の最大公約数を
としたとき、
は
の倍数となります. したがって、それらの和である
も
の倍数となります.
が
の倍数、つまり
は
の約数であることに注意すると、
の候補を全部列挙することができます. (約数を列挙するライブラリを持っていると便利です.)
であることに注意すると、
となります.
を満たす
を用いて、
、
とすることで、最大公約数が
となる数列
を作ることができます.
したがって、の約数でありかつ、
を満たす
の中の最大値を結果として出力してあげれば良いことになります.
#include <iostream> #include <string> #include <vector> #include <cstdlib> #include <cstdio> #include <cmath> #include <algorithm> #include <map> #include <stack> #include <queue> #include <set> #include <cstring> using namespace std; // ascending order #define vsort(v) sort(v.begin(), v.end()) // descending order #define vsort_r(v) sort(v.begin(), v.end(), greater<int>()) #define vunique(v) unique(v.begin(), v.end()) #define mp make_pair #define ts(x) to_string(x) #define rep(i, a, b) for(int i = (int)a; i < (int)b; i++) #define repm(i, a, b) for(int i = (int)a; i > (int)b; i--) #define bit(a) bitset<8>(a) #define des_priority_queue priority_queue<int, vector<int>, greater<int> > #define all(v) (v).begin(), (v).end() typedef long long ll; typedef pair<int, int> P; const ll INF = 1e18; vector<ll> divisor(ll n) { vector<ll> res; for(int i = 1; i * i <= n; i++) { if(n % i == 0) { res.push_back(i); if(i != n / i) res.push_back(n / i); } } return res; } int main(){ cin.tie(0); ios::sync_with_stdio(false); ll N, M; cin >> N >> M; vector<ll> v = divisor(M); ll max_v = 1; rep(i, 0, v.size()) { if(v[i] * N <= M) max_v = max(max_v, v[i]); } cout << max_v << endl; }
感想
C問題に関しては制約を見逃すことが多く、4WA1ACという結果でした...
ここら辺の正確性をどうにかすればもう少し良いレートになれるかなと感じています.
また、整数問題もリアルタイムで解けることが少ないので、練習していく必要がありますね...