链接:https://codeforces.com/gym/104354
A. 小水獭游河南
使用 \(\text{hash}\),\(O(\sum n)\)。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
constexpr int B = 114514;
constexpr i64 P = 1000000000039;
vector<i64> p;
void init(int N) {
p.assign(N, 0);
p[0] = 1;
for (int i = 1; i <= N; i++) {
p[i] = p[i - 1] * B % P;
}
}
struct StringHash {
vector<i64> h;
StringHash() : h(1) {}
void push_back(char ch) {
h.push_back((h.back() * B + ch) % P);
}
i64 toi64(int l, int r) { // [l, r)
return (h[r] + __int128(h[l]) * (P - p[r - l])) % P;
}
};
void solve() {
string s;
cin >> s;
int n = s.size();
StringHash hs;
for (int i = 0; i < n; i++) {
hs.push_back(s[i]);
}
StringHash rhs;
for (int i = n - 1; i >= 0; i--) {
rhs.push_back(s[i]);
}
vector<int> vis(26);
for (int i = 0; i < n - 1; i++) {
if (!vis[s[i] - 'a']) {
vis[s[i] - 'a'] = 1;
if (hs.toi64(i + 1, n) == rhs.toi64(0, n - i - 1)) {
cout << "HE\n";
return;
}
} else {
break;
}
}
cout << "NaN\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
init(1E5);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
B. Art for Rest
前缀最大和后缀最小,\(O(n)\)。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
int inf = 1E9;
vector<int> pre(n + 1), suf(n + 1, inf);
for (int i = 0; i < n; i++) {
pre[i + 1] = max(pre[i], a[i]);
}
reverse(a.begin(), a.end());
for (int i = 0; i < n; i++) {
suf[i + 1] = min(suf[i], a[i]);
}
reverse(suf.begin(), suf.end());
int ans = 0;
for (int i = 1; i <= n; i++) {
bool ok = 1;
for (int j = i; j <= n; j += i) {
if (pre[j] > suf[j]) {
ok = 0;
break;
}
}
ans += (ok == 1);
}
cout << ans << '\n';
return 0;
}
C. Toxel 与随机数生成器
\(\text{kmp}\),\(O(n)\)。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
string s;
cin >> s;
int n = s.size();
vector<int> nex(n + 1);
for (int i = 1, j = 0; i < n; i++) {
while (j && s[i] != s[j]) {
j = nex[j];
}
if (s[i] == s[j]) {
j++;
}
nex[i + 1] = j;
}
for (int i = 0; i <= n; i++) {
if (nex[i] >= 1000) {
cout << "No\n";
return;
}
}
cout << "Yes\n";
return 0;
}
E. 矩阵游戏
dp,\(O(nmx)\)。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
constexpr int N = 500;
constexpr int M = 1000;
int f[N + 1][M + 1];
void solve() {
int n, m, x;
cin >> n >> m >> x;
vector<string> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= x; j++) {
f[i][j] = 0;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
for (int k = x; k >= 0; k--) {
f[j + 1][k] = max(f[j + 1][k], f[j][k]) + (a[i][j] == '1');
if (k && a[i][j] == '?') {
f[j + 1][k] = max(f[j + 1][k - 1], f[j][k - 1]) + 1;
}
}
}
}
cout << f[m][x] << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
F. Art for Last
使用 \(\text{ST}\) 表,\(O(n\log n)\),还有别的方法。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
template <typename T>
struct SparseTable {
int n;
function<T(const T&, const T&)> func;
vector<vector<T>> a;
SparseTable(const vector<T> &init, const function<T(const T&, const T&)> &f) : n(init.size()), func(f) {
int lg = __lg(n);
a.assign(lg + 1, vector<T>(n));
a[0] = init;
for (int i = 1; i <= lg; i++) {
for (int j = 0; j <= n - (1 << i); j++) {
a[i][j] = func(a[i - 1][j], a[i - 1][(1 << (i - 1)) + j]);
}
}
}
T get(int l, int r) {// [l, r)
int lg = __lg(r - l);
return func(a[lg][l], a[lg][r - (1 << lg)]);
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, k;
cin >> n >> k;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
auto b = a;
sort(b.begin(), b.end());
vector<int> c(n - 1);
for (int i = 0; i < n - 1; i++) {
c[i] = b[i + 1] - b[i];
}
auto Min = [&](const int &a, const int &b) {
return min(a, b);
};
SparseTable<int> mn(c, Min);
i64 ans = 1E18;
for (int i = 0; i + k - 1 < n; i++) {
int x = b[i + k - 1] - b[i];
int y = mn.get(i, i + k - 1);
ans = min(ans, 1LL * x * y);
}
cout << ans << '\n';
return 0;
}
G. Toxel 与字符画
模拟。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
using i128 = __int128;
constexpr i64 inf = 1E18;
i64 mul(i64 a, i64 b) {
i128 res = static_cast<i128>(a) * b;
if (res > inf) {
return inf + 1;
}
return res;
}
i64 power(i64 a, i64 b) {
i64 res = 1;
for (; b; b >>= 1, a = mul(a, a)) {
if (b & 1) {
res = mul(res, a);
}
}
return res;
}
vector<string> a = {
"................................................................................",
"................................................................................",
"0000000.......1.2222222.3333333.4.....4.5555555.6666666.7777777.8888888.9999999.",
"0.....0.......1.......2.......3.4.....4.5.......6.............7.8.....8.9.....9.",
"0.....0.......1.......2.......3.4.....4.5.......6.............7.8.....8.9.....9.",
"0.....0.......1.2222222.3333333.4444444.5555555.6666666.......7.8888888.9999999.",
"0.....0.......1.2.............3.......4.......5.6.....6.......7.8.....8.......9.",
"0.....0.......1.2.............3.......4.......5.6.....6.......7.8.....8.......9.",
"0000000.......1.2222222.3333333.......4.5555555.6666666.......7.8888888.9999999.",
"................................................................................"
};
vector<string> b = {
"............................................................",
"00000.....1.22222.33333.4...4.55555.66666.77777.88888.99999.",
"0...0.....1.....2.....3.4...4.5.....6.........7.8...8.9...9.",
"0...0.....1.22222.33333.44444.55555.66666.....7.88888.99999.",
"0...0.....1.2.........3.....4.....5.6...6.....7.8...8.....9.",
"00000.....1.22222.33333.....4.55555.66666.....7.88888.99999.",
"............................................................",
"............................................................",
"............................................................",
"............................................................"
};
vector<string> c = {
"................................",
"................................",
"........IIIIIII.N.....N.FFFFFFF.",
"...........I....NN....N.F.......",
"=======....I....N.N...N.F.......",
"...........I....N..N..N.FFFFFFF.",
"=======....I....N...N.N.F.......",
"...........I....N....NN.F.......",
"........IIIIIII.N.....N.F.......",
"................................"
};
void solve() {
i64 A, B;
scanf("%lld^{%lld}", &A, &B);
int N = 10;
i64 res = power(A, B);
vector<string> ans(N);
for (int i = 0; i < N; i++) {
ans[i] += ".";
}
auto get = [&](const int &l, const int &len, const vector<string> &s) {
for (int i = 0; i < N; i++) {
ans[i] += s[i].substr(l, len);
}
};
string SA = to_string(A);
string SB = to_string(B);
for (auto &x : SA) {
int y = x - '0';
get(y * 8, 8, a);
}
for (auto &x : SB) {
int y = x - '0';
get(y * 6, 6, b);
}
get(0, 8, c);
if (res > inf) {
get(8, 24, c);
} else {
string t = to_string(res);
for (auto &x : t) {
int y = x - '0';
get(y * 8, 8, a);
}
}
for (auto &x : ans) {
cout << x << '\n';
}
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}
H. Travel Begins
贪心,\(O(t)\)。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
void solve() {
int n, k;
cin >> n >> k;
int cnt = min(n * 2, k - 1);
int ans2 = n - cnt / 2 + cnt;
int ans1 = max(0, n - cnt / 2);
cout << ans1 << ' ' << ans2 << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
J. Mocha 沉迷电子游戏
计算几何,分两种情况,\(O(t)\)。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
using Real = double;
using Point = complex<Real>;
const double Pi = acos(-1.0);
void solve() {
int x, y;
cin >> x >> y;
Point p = Point(x, y);
cin >> x >> y;
Point a = Point(x, y);
cin >> x >> y;
Point b = Point(x, y);
int v, t;
cin >> v >> t;
int r = v * t;
Point c = (a + b) / 2.0;
const double pa = abs(p - a);
const double pc = abs(p - c);
const double ab = abs(a - b);
double ans = 0;
const double ad = sqrt(pa * pa - 1LL * r * r);
if (r > pa) {
cout << Pi * r * r << '\n';
return;
}
if (r <= pc) {
ans += ad * r;
ans += pc * ab / 2;
double ang = asin(ad / pa) + asin(ab / 2 / pa);
ans += (Pi - ang) * r * r;
} else {
ans += ad * r * 2;
double ang = asin(ad / pa);
ans += (Pi - 2 * ang) * r * r;
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout << fixed << setprecision(15);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
K. 排列与质数
小的全排列,大的构造,\(O(n)\)。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
if (n < 5) {
cout << -1 << '\n';
return 0;
}
if (n == 5) {
cout << "1 3 5 2 4\n";
return 0;
}
if (n == 6) {
cout << "1 3 5 2 4 6\n";
return 0;
}
if (n == 7) {
cout << "1 3 5 2 7 4 6\n";
return 0;
}
if (n == 8) {
cout << "1 3 5 2 7 4 6 8\n";
return 0;
}
if (n == 9) {
cout << "1 3 5 2 4 7 9 6 8\n";
return 0;
}
if (n == 10) {
cout << "1 3 5 2 4 6 9 7 10 8\n";
return 0;
}
if (n == 11) {
cout << "1 3 5 2 4 6 11 9 7 10 8\n";
return 0;
}
vector<int> ans;
if (n % 2 == 0) {
for (int i = 1; i < n - 1; i += 2) {
ans.push_back(i);
if (i == 5) {
ans.push_back(2);
}
}
for (int i = n; i >= 3; i -= 2) {
ans.push_back(i);
if (i == n - 4) {
ans.push_back(n - 1);
}
}
} else {
for (int i = 1; i <= n; i += 2) {
ans.push_back(i);
if (i == 5) {
ans.push_back(2);
}
if (i == n - 6) {
ans.push_back(n - 1);
}
}
for (int i = n - 3; i >= 4; i -= 2) {
ans.push_back(i);
}
}
for (int i = 0; i < n; i++) {
cout << ans[i] << " \n"[i == n - 1];
}
return 0;
}