ユニークビジョンプログラミングコンテスト2023 春 (AtCoder Beginner Contest 300) - AtCoder
B - Same Map in the RPG World
H,W <= 30 のため 縦方向 shift と横方向 shift を全探索できる
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<n;i++) #define endl '\n' int main() { int h,w; cin >> h >> w; vector<string> a(h),b(h); REP(i,h) cin >> a[i]; REP(i,h) cin >> b[i]; // s: 縦方向shift数, t: 横方向shit数 auto f = [&](int s, int t) { REP(i,h) REP(j,w) { int ni = (i+s) % h; int nj = (j+t) % w; if (a[ni][nj] != b[i][j]) return false; } return true; }; int ok = 0; REP(i,h) REP(j,w) ok |= f(i,j); cout << (ok ? "Yes" : "No") << endl; return 0; }
C - Cross
B と同じく H,W <= 100 のためすべての座標を全探索できる
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<n;i++) #define endl '\n' using P = pair<int,int>; const vector<P> m = { {1,1}, {1,-1}, {-1,1}, {-1,-1} }; int main() { int h,w; cin >> h >> w; vector<string> c(h); REP(i,h) cin >> c[i]; int n = min(h,w); // 座標(i,j)を中心とする x印のサイズを返す auto f = [&](int i, int j) { if (c[i][j] == '.') return 0; int res = 0; for(int k = 1; k <= n; k++) { for(auto [vi,vj]: m) { int ni = i + vi * k; int nj = j + vj * k; if (ni < 0 || nj < 0 || ni >= h || nj >= w) return res; if (c[ni][nj] == '.') return res; } res = k; } return res; }; vector<int> ans(n+1); REP(i,h) REP(j,w) ans[f(i,j)]++; REP(i,n) cout << ans[i+1] << " "; return 0; }
D - AABCC
エラトステネスの篩で素数を列挙し、そこから a < b の組み合わせとなる値を全探索する。
#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; vector<int> eratosthenes(int n) { vector<int> res; vector<bool> is_prime(n+1,true); for(int i = 2; i <= n; i++) { if (!is_prime[i]) continue; for(int j = 2*i; j <= n; j+=i) is_prime[j] = false; res.push_back(i); } return res; } int main() { ll n; cin >> n; auto p = eratosthenes(sqrt(n)); sort(p.begin(),p.end()); int sz = p.size(); int ans = 0; REP(i,sz) for(int j = i+1; j < sz; j++) { ll a = p[i], b = p[j]; ll c = sqrt( n / (a*a*b) ); if (c <= b) break; int idx = upper_bound(p.begin(),p.end(),c) - p.begin(); ans += max(0, idx-j-1); } cout << ans << endl; return 0; }
E - Dice Product 3
abc298 の E - Unfair Sugoroku と似ている。
n の数が 1018 と大きいので計算量が不安になるが、公式解説 にあるように 2a * 3b * 5c で表せる数の個数は大きくないため、メモ化再帰で十分間に合う
#include <bits/stdc++.h> #include <atcoder/all> using namespace atcoder; using namespace std; #define REP(i,n) for(int i=0;i<n;i++) #define endl '\n' using ll = long long; using mint = modint998244353; int main() { ll n; cin >> n; mint p = mint(1)/5; map<ll,mint> mem; auto dfs = [&](auto self, ll now) -> mint { if (now >= n) return now == n ? 1 : 0; if (mem.count(now)) return mem[now]; mint res; for(int i = 2; i <= 6; i++) res += self(self,now*i); res *= p; return mem[now] = res; }; cout << dfs(dfs,1).val() << endl; return 0; }