学到很多……
比赛链接:https://atcoder.jp/contests/abc300/tasks
A - N-choice question
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <bits/stdc++.h> using namespace std;int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ); int n, a, b; cin >> n >> a >> b; for (int i = 0 ; i < n; i++) { int c; cin >> c; if (c == a + b) { cout << i + 1 << "\n" ; return 0 ; } } return 0 ; }
B - Same Map in the RPG World
题解
枚举 s , t s, t s , t 的值。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 #include <bits/stdc++.h> using namespace std;int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ); int h, w; cin >> h >> w; vector a (h, vector<char >(w)) , b (h, vector<char >(w)) ; for (int i = 0 ; i < h; i++) { for (int j = 0 ; j < w; j++) { cin >> a[i][j]; } } for (int i = 0 ; i < h; i++) { for (int j = 0 ; j < w; j++) { cin >> b[i][j]; } } auto cal = [&](int s, int t) { auto c = a; for (int loop = 0 ; loop < s; loop++) { auto d = c; for (int i = 0 ; i < h; i++) { for (int j = 0 ; j < w; j++) { d[i][j] = c[(i + 1 ) % h][j]; } } c = d; } for (int loop = 0 ; loop < t; loop++) { auto d = c; for (int i = 0 ; i < h; i++) { for (int j = 0 ; j < w; j++) { d[i][j] = c[i][(j + 1 ) % w]; } } c = d; } return c; }; for (int i = 0 ; i < h; i++) { for (int j = 0 ; j < w; j++) { if (cal (i, j) == b) { cout << "Yes" << "\n" ; return 0 ; } } } cout << "No" << "\n" ; return 0 ; }
C - Cross
题解
模拟。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include <bits/stdc++.h> using namespace std;int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ); int h, w; cin >> h >> w; vector<string> MP (h) ; for (int i = 0 ; i < h; i++) { cin >> MP[i]; } vector<int > ans (min(h, w)) ; auto legal = [&](int x, int y) { return 0 <= x and x < h and 0 <= y and y < w and MP[x][y] == '#' ; }; for (int i = 0 ; i < h; i++) { for (int j = 0 ; j < w; j++) { int sz = 0 ; while (legal (i - sz, j - sz) and legal (i - sz, j + sz) and legal (i + sz, j - sz) and legal (i + sz, j + sz)) { sz += 1 ; } if (sz >= 2 ) { ans[sz - 2 ] += 1 ; } } } for (int i = 0 ; i < min (h, w); i++) { cout << ans[i] << " \n" [i == min (h, w) - 1 ]; } return 0 ; }
D - AABCC
题解
枚举 a , b a, b a , b 的值。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #include <bits/stdc++.h> using namespace std;constexpr int N = 1e6 + 10 ;vector<bool > is_prime (N, true ) ;vector<long long > primes; void Init () { is_prime[0 ] = is_prime[1 ] = false ; for (int i = 2 ; i < N; i++) { if (not is_prime[i]) { continue ; } primes.push_back (i); for (int j = 2 * i; j < N; j += i) { is_prime[j] = false ; } } } int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ); long long N; cin >> N; Init (); int n = primes.size (); long long ans = 0 ; for (int i = 0 ; i < n; i++) { if (primes[i] >= 252 ) { break ; } for (int j = i + 1 ; j < n; j++) { if (primes[j] >= 10000 ) { break ; } int k = upper_bound (primes.begin (), primes.end (), sqrt (N / primes[i] / primes[i] / primes[j])) - primes.begin () - 1 ; if (k <= j or primes[i] * primes[i] * primes[j] * primes[k] * primes[k] > N) { continue ; } ans += k - j; } } cout << ans << "\n" ; return 0 ; }
E - Dice Product 3
题解
设 d p [ n ] dp[n] d p [ n ] 为得到 n n n 的概率,则有:
d p [ n ] = 1 6 ( d p [ n ] + d p [ n 2 ] + d p [ n 3 ] + d p [ n 4 ] + d p [ n 5 ] + d p [ n 6 ] ) dp[n] = \frac{1}{6}(dp[n] + dp[\frac{n}{2}] + dp[\frac{n}{3}] + dp[\frac{n}{4}] + dp[\frac{n}{5}] + dp[\frac{n}{6}]) d p [ n ] = 6 1 ( d p [ n ] + d p [ 2 n ] + d p [ 3 n ] + d p [ 4 n ] + d p [ 5 n ] + d p [ 6 n ] )
化简得:
d p [ n ] = 1 5 ( d p [ n 2 ] + d p [ n 3 ] + d p [ n 4 ] + d p [ n 5 ] + d p [ n 6 ] ) dp[n] = \frac{1}{5}(dp[\frac{n}{2}] + dp[\frac{n}{3}] + dp[\frac{n}{4}] + dp[\frac{n}{5}] + dp[\frac{n}{6}]) d p [ n ] = 5 1 ( d p [ 2 n ] + d p [ 3 n ] + d p [ 4 n ] + d p [ 5 n ] + d p [ 6 n ] )
利用记忆化进行搜索。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 #include <bits/stdc++.h> using namespace std;constexpr int MOD = 998244353 ;int norm (int x) { if (x < 0 ) { x += MOD; } if (x >= MOD) { x -= MOD; } return x; }template <class T> T binpow (T a, int b) { T res = 1 ; for (; b; b /= 2 , a *= a) { if (b % 2 ) { res *= a; } } return res; }struct Z { int x; Z (int x = 0 ) : x (norm (x)) {} int val () const { return x; } Z operator -() const { return Z (norm (MOD - x)); } Z inv () const { assert (x != 0 ); return binpow (*this , MOD - 2 ); } Z &operator *=(const Z &rhs) { x = 1LL * x * rhs.x % MOD; return *this ; } Z &operator +=(const Z &rhs) { x = norm (x + rhs.x); return *this ; } Z &operator -=(const Z &rhs) { x = norm (x - rhs.x); return *this ; } Z &operator /=(const Z &rhs) { return *this *= rhs.inv (); } friend Z operator *(const Z &lhs, const Z &rhs) { Z res = lhs; res *= rhs; return res; } friend Z operator +(const Z &lhs, const Z &rhs) { Z res = lhs; res += rhs; return res; } friend Z operator -(const Z &lhs, const Z &rhs) { Z res = lhs; res -= rhs; return res; } friend Z operator /(const Z &lhs, const Z &rhs) { Z res = lhs; res /= rhs; return res; } }; int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ); long long n; cin >> n; map<long long , Z> mp; mp[1 ] = 1 ; function<Z(long long )> dfs = [&](long long cur) { if (mp.count (cur)) { return mp[cur]; } else { Z res = 0 ; for (int i = 2 ; i <= 6 ; i++) { if (cur % i == 0 ) { res += dfs (cur / i); } } return mp[cur] = res / 5 ; } }; cout << dfs (n).val () << "\n" ; return 0 ; }
F - More Holidays
题解
observation:一定存在一种最优方案,操作后连续 o
的左端点在前 n n n 个字符内。
proof:假设存在一种最优方案不以前 n n n 个字符的左端点为起点,则可以操作的每个字符的位置都向左提前 n n n 个。
所以在前 n n n 个字符内枚举连续 o
的左端点,贪心地操作后面的 x
即可。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 #include <bits/stdc++.h> using namespace std;int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ); long long n, m, k; cin >> n >> m >> k; string s; cin >> s; vector<int > cnt (n + 1 ) ; for (int i = 0 ; i < n; i++) { cnt[i + 1 ] = cnt[i] + (s[i] == 'x' ); } vector<int > pos; pos.push_back (-1 ); for (int i = 0 ; i < n; i++) { if (s[i] == 'x' ) { pos.push_back (i); } } long long ans = 0 ; auto cal = [&](int i) { int id = lower_bound (pos.begin (), pos.end (), i) - pos.begin (); long long res = i - pos[id - 1 ] - 1 ; long long suf = cnt[n] - cnt[i]; long long t_k = k; if (t_k < suf) { return res + pos[id + t_k] - i; } else { res += n - i; t_k -= suf; res += t_k / cnt[n] * n; t_k %= cnt[n]; res += pos[t_k + 1 ]; return min (res, n - pos[id - 1 ] - 1 + (m - 1 ) * n); } }; for (int i = 0 ; i < n; i++) { ans = max (ans, cal (i)); } cout << ans << "\n" ; return 0 ; }
G - P-smooth number
题解
枚举,用到了一种被称为 meet in the middle
的搜索技巧,具体可以参考这篇博客 。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 #include <bits/stdc++.h> using namespace std;vector<int > minp, primes; void Init (int n) { minp.assign (n + 1 , 0 ); primes.clear (); for (int i = 2 ; i <= n; i++) { if (minp[i] == 0 ) { minp[i] = i; primes.push_back (i); } for (auto p : primes) { if (i * p > n) { break ; } minp[i * p] = p; if (p == minp[i]) { break ; } } } } int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ); long long n, p; cin >> n >> p; Init (p); vector<long long > a{1 }, b{1 }; auto cal = [&](auto & vec, int fac) { int sz = vec.size (); for (int i = 0 ; i < sz; i++) { long long x = vec[i] * fac; while (x <= n) { vec.push_back (x); x *= fac; } } }; for (auto fac : primes) { if (a.size () < b.size ()) { cal (a, fac); } else { cal (b, fac); } } sort (a.begin (), a.end ()); sort (b.begin (), b.end ()); long long ans = 0 ; for (int i = (int )b.size () - 1 ; auto x : a) { while (i >= 0 and x * b[i] > n) { i--; } if (i >= 0 ) { ans += i + 1 ; } } cout << ans << "\n" ; return 0 ; }