Bondo416さんのエイシング プログラミング コンテスト 2020での成績:1942位
— ボンド@競プロ (@bond_cmprog) July 11, 2020
パフォーマンス:1161相当
レーティング:1297→1284 (-13) :(#AtCoder #エイシングプログラミングコンテスト2020 https://t.co/ctdC5h4lZw
A - Number of Multiples
を求めるやつ
制約が小さいので全探索でいい
提出コード
void solve(){ int L, R, D; cin >> L >> R >> D; int ans = 0; for(int i=L;i<=R;i++) if(i % D == 0) ans++; cout << ans << endl; }
B - An Odd Problem
とがどちらも奇数のものをカウントする
提出コード
void solve(){ int N; cin >> N; vector<int> a(N+1); int ans = 0; for(int i=1;i<=N;i++){ cin >> a[i]; if((i & 1) && (a[i] & 1)) ans++; } cout << ans << endl; }
C - XYZ Triplets
を考えるとのときになるので
程度で全探索すればいい
提出コード
void solve(){ int N; cin >> N; vector<int> cnt(N+10); for(ll i=1;i<=300;i++){ for(ll j=1;j<=300;j++){ for(ll k=1;k<=300;k++){ ll x = i*i + j*j + k*k + i*j + j*k + k*i; if(x > N) continue; cnt[x]++; } } } for(int i=1;i<=N;i++) cout << cnt[i] << endl; }
D - Anything Goes to Zero
最初の1回目の操作を考えると最大でもで割った余りを求めるので、一回目の操作の値を求めることが出来れば、後は愚直に操作が出来る
1回の操作での値はの2通りしか無いのでを前計算しておく
そうすると、一回目の操作後の値は、そのbitを反転させたときの差分と、前計算した2通りのどちらかのmodを使って求めることが出来る
二回目以降は愚直に操作をすればいい
ただし、操作を行ったときに0になる時の場合分けが必要
提出コード
void solve(){ int N; string S; cin >> N >> S; int cnt = 0; reverse(S.begin(), S.end()); REP(i,N) if(S[i] == '1') cnt++; ll x1 = 0, x2 = 0; REP(i,N){ if(S[i] == '1'){ if(cnt > 1){ x1 += mod_pow(2, i, cnt-1); x1 %= (cnt - 1); } x2 += mod_pow(2, i, cnt+1); x2 %= (cnt + 1); } } vector<int> ans(N); REP(i,N){ if(S[i] == '1'){ if(cnt == 1){ ans[i] = 0; continue; } ll tmp = x1 - mod_pow(2, i, cnt - 1) + (cnt - 1); tmp %= (cnt - 1); ans[i]++; while(tmp > 0){ ans[i]++; tmp %= __builtin_popcount(tmp); } } else{ ll tmp = x2 + mod_pow(2, i, cnt+1); tmp %= (cnt + 1); ans[i]++; while(tmp > 0){ ans[i]++; tmp %= __builtin_popcount(tmp); } } } reverse(ans.begin(), ans.end()); REP(i,N) cout << ans[i] << endl; }
E - Camel Train
とに分けて考える
前者は出来るだけ左側に寄せて、後者は出来るだけ右側に寄せた方がお得
後者より右側に前者が存在する場合、その部分を入れ替えても損をすることは無いので、それぞれ独立に考えても良いことがわかる
前者を考えると、どの位置においても最低は得られる
ラクダが番目以内にいる時、が追加で得られる
そうすると、制約がきついほうから考えると左側から順にとなるようなラクダのをpriority_queueに入れていき、なら小さい方から取り除いていき、残ったものの総和を加算する
後者の場合も同様に右側から順に処理をしていき、最後に残ったものの総和を加算する
提出コード
void solve(){ int N; cin >> N; vector<vector<ll>> vp(N+10), vm(N+10); ll ans = 0; int cnt = 0; REP(i,N){ int K, L, R; cin >> K >> L >> R; if(L >= R){ vp[K].emplace_back(L - R); ans += R; cnt++; } else{ ans += L; vm[K].emplace_back(R - L); } } priority_queue<ll, vector<ll>, greater<ll>> pq, pq2; for(int i=1;i<=N;i++){ for(auto x : vp[i]) pq.emplace(x); while(size(pq) > i) pq.pop(); } while(!pq.empty()) ans += pq.top(), pq.pop(); for(int i=N;i>=1;i--){ for(auto x : vm[i]) pq2.emplace(x); while(size(pq2) > N - i) pq2.pop(); } while(!pq2.empty()) ans += pq2.top(), pq2.pop(); cout << ans << endl; }