冷えたけど復習してたら楽しくなっちゃった(?)
Bondo416さんのAtCoder Beginner Contest 171での成績:3679位
— ボンド@競プロ (@bond_cmprog) June 21, 2020
パフォーマンス:878相当
レーティング:1304→1268 (-36) :(#AtCoder #ABC171 https://t.co/9owh9bxNYX
A - αlphabet
'a'~'z'もしくは'A'~'Z'はASCIIコードでは連続になっているので小文字もしくは大文字かどうかを判定できる
提出コード
void solve(){ char c; cin >> c; if('A' <= c && c <= 'Z') cout << "A" << endl; else cout << "a" << endl; }
B - Mix Juice
昇順にソートし、小さい方からK個の合計を出力
提出コード
void solve(){ int N, K; cin >> N >> K; vector<int> p(N); REP(i,N) cin >> p[i]; sort(p.begin(), p.end()); int sum = 0; REP(i,K) sum += p[i]; cout << sum << endl; }
C - One Quadrillion and One Dalmatians
難しい
26進数っぽいものを求めて出力すればいい
1文字目を考えると'a'が1に対応しているので0-indexedに戻してあげる
次に桁上りした場合、その桁が1から始まるがこの問題だと0(='a')にならないといけない
そのため、各桁ごとに予め1引いた状態で26進数を求めればいい
提出コード
void solve(){ ll N; cin >> N; string ans = ""; while(N > 0){ N--; ans += char('a' + N % 26); N /= 26; } reverse(ans.begin(), ans.end()); cout << ans << endl; }
D - Replacing
一瞬区間クエリだと思って激ムズでは?となった
数列のある要素を全部書き換えるようなクエリなので、現時点での総和と各値が何個あるかをvectorなどで管理する
そうすると、数列中のをすべてに変えたときの総和はその都度差分を考えることで求めることが出来る
提出コード
void solve(){ int N; cin >> N; vector<ll> cnt(101010); ll sum = 0; REP(i,N){ int A; cin >> A; cnt[A]++; sum += A; } int Q; cin >> Q; REP(i,Q){ int B, C; cin >> B >> C; ll tmp_cnt = cnt[B]; ll tmp_sum = tmp_cnt * B; cnt[B] = 0; cnt[C] += tmp_cnt; sum -= tmp_sum; sum += tmp_cnt * C; cout << sum << endl; } }
E - Red Scarf
出力する数列をとする
この時
...
のようになる
のように同じもののxorは0になるので1個だけ残るようにxor出来ないかを考えてみる
そうすると、のように自分を除いたもの以外のxorの合計がとなる
これは、左右からの累積xorのようなものを事前に計算しておくと出来る
全体のxorからのxor取るのでも同じ様になるんだけど、その発想出てこなかったな
提出コード
void solve(){ int N; cin >> N; vector<int> a(N); REP(i,N) cin >> a[i]; vector<int> left(N), right(N); left[0] = a[0], right[N-1] = a[N-1]; for(int i=1;i<N;i++) left[i] = left[i-1] ^ a[i]; for(int i=N-2;i>=0;i--) right[i] = right[i+1] ^ a[i]; REP(i,N){ if(i == 0) cout << right[i+1] << " "; else if(i == N-1) cout << left[i-1] << " "; else cout << (left[i-1] ^ right[i+1]) << " "; } cout << endl; }
F - Strivore
教えてもらってなんとか理解できた(教えてくれた人ありがとう)
まず、適当に操作を行うと重複が出来てしまうので、操作と結果が1対1になるようにしたい
今回の場合、文字列Sに操作を行って出来たときの文字列をTとする
Tの先頭から貪欲に部分文字列を選んでSにするとき、その選んだindexが必ず辞書順最小となるように操作を行って文字列Tを作ることを考える
そうすると例えば、S="abc"とした時
'a'の左側には'a'以外の25文字、'a'と'b'の間は'b'以外の25文字、'b'と'c'の間は'c'以外の25文字、'c'より右側は好きな26文字すべておける
より左側に文字、右側に文字置くかを考え、の場合を加算する
を固定したときは、左側はそれぞれ通りで、を個の中からどこに置くかで通り、右側は通りあるので全体で
通りとなる
求めた答えは、実は文字列Sの各文字に依存しないことがわかる、これすごい
提出コード
using mint = Fp<MOD>; BiCoef<mint> bc(2020202); void solve(){ int K; string S; cin >> K >> S; int N = S.size(); mint ans = 0; for(int i=0;i<=K;i++){ ans += modpow(mint(25), i) * bc.com(N-1+i, N-1) * modpow(mint(26), K-i); } cout << ans << endl; }