Tasks - AtCoder Beginner Contest 349
B - Commencement
英小文字の出現回数を数える。その出現回数毎の回数を数えて、すべて 0 または 2 回であれば Yes
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<n;i++) #define endl '\n' int main() { string s; cin >> s; vector<int> cnt1(26); for(auto c: s) cnt1[c-'a']++; vector<int> cnt2(101); REP(i,26) cnt2[cnt1[i]]++; int ok = 1; for(int i = 1; i <= 100; i++) ok &= (cnt2[i] == 0 || cnt2[i] == 2); cout << (ok ? "Yes" : "No") << endl; return 0; }
C - Airport Code
S の先頭から T の文字とマッチするものがあるか貪欲に調べていけばよい。文字数が足りない場合は末尾に X を足して、T とマッチすれば Yes
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<n;i++) #define endl '\n' int main() { string s,t; cin >> s >> t; REP(i,3) t[i] = tolower(t[i]); int now = 0; string ns = ""; for(auto c: s) if (c == t[now]) { now++; ns += c; } if (ns.size() == 2) ns += 'x'; cout << (ns == t ? "Yes" : "No") << endl; return 0; }
D - Divide Interval
L の値からシミュレーションする。 - 奇数の場合は 20 * L, 20 * (L+1) しかあり得ない - 偶数の場合は、260 から最も大きい範囲を取れる数を調べる
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<n;i++) #define endl '\n' using ll = long long; using P = pair<ll,ll>; int main() { ll l,r; cin >> l >> r; vector<P> ans; while(l < r) { if (l%2) { ans.emplace_back(l,l+1); l = l+1; } else { for(ll i = 60; i >= 0; i--) { ll p = 1LL<<i; if (l % p) continue; ll nl = p * (l / p + 1); if (nl > r) continue; ans.emplace_back(l,nl); l = nl; break; } } } cout << ans.size() << endl; for(auto [k,v]: ans) cout << k << " " << v << endl; return 0; }
E - Weighted Tic-Tac-Toe
お互い利益が最大になるように動く必要がある。こういうときはミニマックス法が使える。 ミニマックス法 - Wikipedia
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<n;i++) #define endl '\n' using ll = long long; const ll LINF = 1e18; int main() { vector a(3,vector<int>(3)); REP(i,3) REP(j,3) cin >> a[i][j]; // used[i][j] := takahashi が置いたときは 1, aoki が置いたときは -1 vector used(3,vector<int>(3)); // マス{i,j}にターン t が置いたとき、タテ・ヨコ・ナナメいずれかが揃って勝てるか? auto win = [&](int i, int j, int t) { int res = 0, s = 3*t; used[i][j] = t; REP(i,3) res |= used[i][0] + used[i][1] + used[i][2] == s; REP(j,3) res |= used[0][j] + used[1][j] + used[2][j] == s; res |= used[0][0] + used[1][1] + used[2][2] == s; res |= used[0][2] + used[1][1] + used[2][0] == s; used[i][j] = 0; return res; }; auto dfs = [&](auto self, int cnt, ll score) -> ll { if (cnt == 9) return score; // takahashi のターンは 1, aoki のターンは -1 int t = cnt % 2 ? -1 : 1; ll res = -t*LINF; REP(i,3) REP(j,3) { if (used[i][j] != 0) continue; // 既に使われている if (win(i,j,t)) return t*LINF; // 3マス揃って勝てる場合 used[i][j] = t; res = (t == 1) ? max(res,self(self,cnt+1,score+a[i][j])) : min(res,self(self,cnt+1,score-a[i][j])); used[i][j] = 0; } return res; }; ll ans = dfs(dfs,0,0); cout << (ans > 0 ? "Takahashi" : "Aoki") << endl; return 0; }