ABC194に参加しました
AtCoderのコンテストに参加した際の結果と考え方、反省点などを書いていきます。
コンテストページはこちら
解いた/挑んだ問題
A問題
問題の概要
アイス製品は乳固形分と乳脂肪分により4つに大別されます。
乳固形分は無脂乳固形分と乳脂肪分の2つからなり、
スヌケアイスには、無脂乳固形分がA%、乳脂肪分がB%含まれています。
アイス製品はそれぞれ
・乳固形分が15%以上で、乳脂肪分が8%以上のものを「アイスクリーム」
・上に当てはまらず、乳固形分が10%以上で、乳脂肪分が3%以上のものを「アイスミルク」
・上に当てはまらず、乳固形分が3%以上のものを「ラクトアイス」
・どれにも当てはまらないものは「氷菓」とする
スヌケアイスはどの種類になりますか
制約
- は整数
どのように考えたか
入力では乳固形分が与えられないので、乳固形分を計算して変数に入れて
4通りの場合分けをした
結果
1発AC
・提出したコード
#include<bits/stdc++.h> #include<atcoder/all> #define rep(i, n) for (long long i = 0; i < (long long)(n); i++) #define REP(i,v,n) for(long long i = v; i <= (long long)(n); i++) #define rrep(i,n) for(long long i = n;0 <= (long long)(i); i--) #define RREP(i,n,v) for(long long i = n;v <= (long long)(i); i--) #define all(v) v.begin(), v.end() #define rall(v) v.rbegin(), v.rend() template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; } template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; } using namespace std; using namespace atcoder; using ll = long long; using pi = pair<int, int>; ll pows(ll x, ll n) {ll ret = 1;while (n > 0) {if (n & 1) ret *= x;x *= x;n >>= 1;}return ret;} int main() { int a,b,ans,c; cin >> a >> b; c = a + b; if(15 <= c && 8 <= b)ans = 1; else if(10 <= c && 3 <= b)ans = 2; else if(3 <= c)ans = 3; else ans = 4; cout << ans << endl; return 0; }
A問題にしては問題文が難しかった
ACまでの時間
ACしたのはコンテスト開始から4分後です。
B問題
問題の概要
ある会社には従業員が人おり、従業員は仕事Aを分、仕事Bを分でこなすことができます。
同じ従業員が仕事を行うと、Aの時間とBの時間の合算で仕事が終わります。
違う従業員が仕事を行うと、Aの時間とBの時間の短いほうの時間で仕事が終わります。
2つの仕事が終わるのに最短で何分かかりますか
制約
- 入力は全て整数
どのように考えたか
全ての従業員が2つの仕事をこなした時の最小値を取り、
2つの仕事を違う従業員がこなした時の時間を全探索し、最小値をとった
結果
1発AC
提出したコード
#include<bits/stdc++.h> #include<atcoder/all> #define rep(i, n) for (long long i = 0; i < (long long)(n); i++) #define REP(i,v,n) for(long long i = v; i <= (long long)(n); i++) #define rrep(i,n) for(long long i = n;0 <= (long long)(i); i--) #define RREP(i,n,v) for(long long i = n;v <= (long long)(i); i--) #define all(v) v.begin(), v.end() #define rall(v) v.rbegin(), v.rend() template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; } template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; } using namespace std; using namespace atcoder; using ll = long long; using pi = pair<int, int>; ll pows(ll x, ll n) {ll ret = 1;while (n > 0) {if (n & 1) ret *= x;x *= x;n >>= 1;}return ret;} int main() { int n,ans = 1001001001; cin >> n; vector<int>A(n),B(n); rep(i,n)cin >> A[i] >> B[i]; rep(i,n){ chmin(ans,A[i] + B[i]); } int tmp; rep(i,n){ rep(j,n){ if(i == j)continue; chmin(ans,max(A[i] , B[j])); } } cout << ans << endl; return 0; }
全探索をすればいいなと思えたので比較的簡単だった
ACまでの時間
ACしたのはコンテスト開始から9分後です。
C問題
問題の概要
長さの数列が与えられます。
を求めてください
制約
- 入力は全て整数
どのように考えたか
愚直にやるとTLEするので、計算量の削減を考えます
を展開すると、になります。
数列A = [3,4,5]とした場合、
となり、前半の二つを展開するとそれぞれ
となり、
これは、として、の部分との部分をまとめて計算することができます。
なので、より右にある数値をすべて足した配列を事前に計算しておくと、を高速に計算できそうです。
また、の部分も、より右にある数値を二乗してすべて足した配列を事前に計算しておくと高速に計算できます。
に掛ける数値もより右にある数値の数なので、簡単に求めることができ、
の範囲におけるの合計値をO(1)で計算することができます。
結果
3回目でAC
・提出したコード
#include<bits/stdc++.h> #include<atcoder/all> #define rep(i, n) for (long long i = 0; i < (long long)(n); i++) #define REP(i,v,n) for(long long i = v; i <= (long long)(n); i++) #define rrep(i,n) for(long long i = n;0 <= (long long)(i); i--) #define RREP(i,n,v) for(long long i = n;v <= (long long)(i); i--) #define all(v) v.begin(), v.end() #define rall(v) v.rbegin(), v.rend() template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; } template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; } using namespace std; using namespace atcoder; using ll = long long; using pi = pair<int, int>; ll pows(ll x, ll n) {ll ret = 1;while (n > 0) {if (n & 1) ret *= x;x *= x;n >>= 1;}return ret;} int main() { int n=0; ll ans = 0,kake=0; cin >> n; vector<ll>arr(n),one(n-1,0),two(n-1,0); rep(i,n)cin >> arr[i]; one[n-2] = arr[n-1]; two[n-2] = arr[n-1] * arr[n-1]; for(int i = n-2;1 <=i;i--){ one[i-1] = one[i] + arr[i]; two[i-1] = two[i] + arr[i] * arr[i]; } rep(i,n-1){ kake = n - (i+1); ll x = arr[i],y = one[i],z = two[i]; ans += (kake * x*x) -(2*x*y) + z; } cout << ans << endl; // printf("%lld\n",ans); return 0; }
展開して計算量の削減を見つけられたのはよかったが、配列外参照とint型のオーバーフローで2ペナを出してしまったのが痛かった
ACまでの時間
ACしたのはコンテスト開始から59分後。
コンテスト結果
ABCの3完でした。
C問題で時間を使いすぎて、ほかの問題を最後までつめきれなかった
パフォーマンス、レーティング変動
今回のパフォーマンスは638、前回より70近くあがりました。
レーティングはそれに伴い-5の683となりました。
反省点
今回は、すぐに式展開をして計算量の削減を図れたのはよかったが、配列外参照でエラーが起き
その原因をなかなか特定できなかったのがとても痛いところです。
E問題もチャレンジしてみて、最後の最後で詰め切れずWAだったので、今回は自分の甘さが出てしまったのかなと思います。
最近なかなか成果が振るわないので、どこかで大逆転できるようにこれからも精進していきたいです。