B Hash
题解:
根据官方题解可以得出,子串长度不大于15为最佳长度(证明过程没看懂)。
容易看出哈希函数是以31为进制的,将模数设为P,那么一个数在模P且不大于P的情况下,越接近于P值是越大的。
盲猜子串的长度也是不会太长。
然后进行暴力DP,因为题目中的字符串是一个环,所以我们需要先枚举第一个子串的起始位置,而子串不大于15,我们只需要枚举15位即可,接下来就是进行dp转移。
f
[
i
]
f[i]
f[i] 表示以第
i
i
i 个字符结尾的哈希值之和
转移方程:
d
p
[
i
]
=
max
0
≤
k
<
15
d
p
[
i
−
k
]
+
f
(
i
−
k
+
1
,
i
)
dp[i]=\max_{0\le k< 15}dp[i-k]+ f(i-k+1,i)
dp[i]=max0≤k<15dp[i−k]+f(i−k+1,i)
时间复杂度:O(
1
5
2
∣
S
∣
15^2|S|
152∣S∣)
template<int T>
struct ModInt {
const static int MD = T;
int x = 0;
ModInt(LL x = 0) : x(x% MD) {}
int get() { return x; }
ModInt operator + (const ModInt& that) const { int x0 = x + that.x; return ModInt(x0 < MD ? x0 : x0 - MD); }
ModInt operator - (const ModInt& that) const { int x0 = x - that.x; return ModInt(x0 < MD ? x0 + MD : x0); }
ModInt operator * (const ModInt& that) const { return ModInt((long long)x * that.x % MD); }
ModInt operator / (const ModInt& that) const { return *this * that.inverse(); }
void operator += (const ModInt& that) { x += that.x; if (x >= MD) x -= MD; }
void operator -= (const ModInt& that) { x -= that.x; if (x < 0) x += MD; }
void operator *= (const ModInt& that) { x = (long long)x * that.x % MD; }
void operator /= (const ModInt& that) { *this = *this / that; }
ModInt inverse() const {
int a = x, b = MD, u = 1, v = 0;
while (b) {
int t = a / b;
a -= t * b; std::swap(a, b);
u -= t * v; std::swap(u, v);
}
if (u < 0) u += MD;
return u;
}
};
typedef ModInt<mod> mint;
//取模的板子
LL f[N];
mint h[N], p[N], P = 31;
mint get_hash(int l, int r)
{
return h[r] - h[l - 1] * p[r - l + 1];
}
void solve()
{
unordered_map<char, int> mp;
mp['a'] = 1, mp['e'] = 2, mp['h'] = 3, mp['n'] = 4;
string s; cin >> s;
int n = s.size();
s = " " + s + s;
p[0] = 1;
for (int i = 1; i <= n + 20; i ++ )
{
p[i] = p[i - 1] * P;
h[i] = h[i - 1] * P + mp[s[i]];
}
LL ans = 0;
for (int j = 1; j <= 16; j ++ )
{
for (int i = 0; i < n + 20; i ++ ) f[i] = 0;
for (int i = j; i <= n + j - 1; i ++ )
{
for (int k = 0; k <= 15; k ++ )
{
int l = max(j - 1, i - k);
ModInt t = get_hash(l + 1, i);
f[i] = max(f[i], f[l] + t.get());
}
}
ans = max(ans, f[n + j - 1]);
}
cout << ans << "\n";
}
int main()
{
IOS; cin.tie(0); cout.tie(0);
//int T; cin >> T;
//while (T -- ) solve();
solve();
return 0;
}
C Serval 的试卷答案
struct node
{
int l, r, left, right;
int cnt, lz;
int c[4][4], tmp[4][4];
}tr[N << 2];
LL f[N], inf[N];
LL ksm(LL a, LL b)
{
LL res = 1;
while (b)
{
if (b & 1) res = res * a % mod;
b >>= 1;
a = a * a % mod;
}
return res;
}
void init()
{
f[0] = 1;
for (int i = 1; i <= 1e5; i ++ ) f[i] = f[i - 1] * i % mod;
inf[100000] = ksm(f[100000], mod - 2);
for (int i = 99999; i >= 0; i -- )
inf[i] = inf[i + 1] * (i + 1) % mod;
}
LL C(int a, int b)
{
return f[a] * inf[b] % mod * inf[a - b] % mod;
}
void change(node &u, int t)
{
u.cnt = 0;
u.left = (u.left + t) % 4, u.right = (u.right + t) % 4;
for (int i = 0; i < 4; i ++ )
for (int j = 0; j < 4; j ++ )
u.tmp[i][j] = u.c[i][j];
for (int i = 0; i < 4; i ++ )
for (int j = 0; j < 4; j ++ )
u.c[(i + t) % 4][(j + t) % 4] = u.tmp[i][j];
for (int i = 0; i < 4; i ++ )
for (int j = 0; j < 4; j ++ )
if (i >= j) u.cnt += u.c[i][j];
}
void push_up(node &u, node &l, node &r)
{
u.left = l.left, u.right = r.right;
u.cnt = l.cnt + r.cnt;
for (int i = 0; i < 4; i ++ )
for (int j = 0; j < 4; j ++ )
u.c[i][j] = l.c[i][j] + r.c[i][j];
u.c[l.right][r.left] ++;
if (l.right >= r.left) u.cnt ++;
}
void push_down(node &u, node &l, node &r)
{
if (!u.lz) return;
l.lz += u.lz, r.lz += u.lz;
change(l, u.lz), change(r, u.lz);
u.lz = 0;
}
void build(int u, int l, int r)
{
tr[u] = {l, r};
if (l == r)
{
char ch; cin >> ch;
tr[u].left = tr[u].right = ch - 'A';
return;
}
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
push_up(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
void modify(int u, int l, int r)
{
if (tr[u].l >= l && tr[u].r <= r)
{
change(tr[u], 1);
tr[u].lz ++;
return;
}
push_down(tr[u], tr[u << 1], tr[u << 1 | 1]);
int mid = tr[u].l + tr[u].r >> 1;
if (l <= mid) modify(u << 1, l, r);
if (r > mid) modify(u << 1 | 1, l, r);
push_up(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
int query(int u, int l, int r)
{
if (tr[u].l >= l && tr[u].r <= r)
return tr[u].cnt;
push_down(tr[u], tr[u << 1], tr[u << 1 | 1]);
int res = 0, flag = 0;
int mid = tr[u].l + tr[u].r >> 1;
if (l <= mid) res += query(u << 1, l, r), flag ++;
if (r > mid) res += query(u << 1 | 1, l, r), flag ++;
if (flag == 2 && tr[u << 1].right >= tr[u << 1 | 1].left) res ++;
return res;
}
void solve()
{
init();
int n, m; cin >> n >> m;
build(1, 1, n);
while (m -- )
{
int op; cin >> op;
if (op == 1)
{
int l, r; cin >> l >> r;
modify(1, l, r);
// cout << query(1, 1, n) << "\n";
}
else
{
int l, r, k; cin >> l >> r >> k;
int c = query(1, l, r);
// cout << c << "\n";
if (r - l + 1 < k || k < c + 1) cout << "0\n";
else cout << C(r - l - c, k - 1 - c) << "\n";
}
}
// cout << query(1, 1, n) << "\n";
}
int main()
{
IOS; cin.tie(0); cout.tie(0);
//int T; cin >> T;
//while (T -- ) solve();
solve();
return 0;
}
E. Serval 的俳句
int cnt[26];
void solve()
{
int n; cin >> n;
string s; cin >> s;
char c1 = ' ', c2 = ' ', c3 = ' ';
for (int i = 0; i < n; i ++ )
{
cnt[s[i] - 'a'] ++;
if (c1 == ' ')
{
if (cnt[s[i] - 'a'] == 5)
{
c1 = s[i];
for (int i = 0; i < 26; i ++ ) cnt[i] = 0;
}
continue;
}
if (c2 == ' ')
{
if (cnt[s[i] - 'a'] == 7)
{
c2 = s[i];
for (int i = 0; i < 26; i ++ ) cnt[i] = 0;
}
continue;
}
if (c3 == ' ')
{
if (cnt[s[i] - 'a'] == 5)
{
c3 = s[i];
for (int i = 0; i < 26; i ++ ) cnt[i] = 0;
}
continue;
}
}
if (c1 == ' ' || c2 == ' ' || c3 == ' ') cout << "none\n";
else
{
for (int i = 0; i < 5; i ++ ) cout << c1;
for (int i = 0; i < 7; i ++ ) cout << c2;
for (int i = 0; i < 5; i ++ ) cout << c3;
}
}
int main()
{
IOS; cin.tie(0); cout.tie(0);
//int T; cin >> T;
//while (T -- ) solve();
solve();
return 0;
}
H 旋转水管
char g[5][N];
int sx, sy, tx, ty, m;
bool f[5][N], flag;
bool check(int x, int y)
{
return (x >= 2 && x <= 4 && y >= 1 && y <= m);
}
void dfs(int x, int y, int k)
{
if (flag) return;
if (x == tx)
{
if (y == ty) flag = true;
return;
}
f[x][y] = true;
if (g[x][y] == 'I')
{
int nx, ny;
if (k == 0)
nx = x + 1, ny = y;
else if (k == 1)
nx = x, ny = y - 1;
else if (k == 2)
nx = x - 1, ny = y;
else
nx = x, ny = y + 1;
if (check(nx, ny) && !f[nx][ny])
dfs(nx, ny, k);
}
else
{
int nx, ny;
if (k == 0 || k == 2)
{
nx = x, ny = y + 1;
if (check(nx, ny) && !f[nx][ny])
dfs(nx, ny, 3);
ny = y - 1;
if (check(nx, ny) && !f[nx][ny])
dfs(nx, ny, 1);
}
else
{
nx = x - 1, ny = y;
if (check(nx, ny) && !f[nx][ny])
dfs(nx, ny, 2);
nx = x + 1;
if (check(nx, ny) && !f[nx][ny])
dfs(nx, ny, 0);
}
}
f[x][y] = false;
}
void solve()
{
int x, y;
cin >> m >> x >> y;
for (int i = 2; i <= 4; i ++ )
for (int j = 1; j <= m; j ++ )
g[i][j] = false;
for (int i = 2; i <= 3; i ++ )
for (int j = 1; j <= m; j ++ )
cin >> g[i][j];
sx = 2, sy = x, tx = 4, ty = y;
flag = false;
dfs(sx, sy, 0);
if (flag) cout << "YES\n";
else cout << "NO\n";
}
int main()
{
IOS; cin.tie(0); cout.tie(0);
int T; cin >> T;
while(T -- ) solve();
//solve();
return 0;
}
I Oshwiciqwq 的电梯
int n, m, h, k, q;
struct node
{
int pi, ei, x, y, z;
string st;
bool operator < (const node &t) const
{
if (ei != t.ei) return ei < t.ei;
if (st != t.st) return st > t.st;
return pi < t.pi;
}
};
vector<node> v[1100];
vector<array<int, 4>> e[5];
int get_pos(int x, int t, int p)
{
int res = (x + t) % p;
if (res == 0) res = p;
return res;
}
int get_t(int x1, int x2, int p)
{
if (x2 >= x1) return x2 - x1;
return x2 + p - x1;
}
void solve()
{
cin >> n >> m >> h >> k;
for (int i = 1; i <= k; i ++ )
{
int t, x, y, z; cin >> t >> x >> y >> z;
e[t].push_back({i, x, y, z});
}
cin >> q;
int time = 0;
for (int i = 1; i <= q; i ++ )
{
int t, fx, fy, fz, tx, ty, tz;
cin >> t >> fx >> fy >> fz >> tx >> ty >> tz;
int f = 0;
if (fx != tx)
{
for (auto &[id, x, y, z] : e[0])
{
if (y == fy && z == fz)
{
int pos = get_pos(x, t, n);
t += get_t(pos, fx, n);
v[t].push_back({i, id, fx, fy, fz, "IN"});
t += get_t(fx, tx, n);
fx = tx;
v[t].push_back({i, id, fx, fy, fz, "OUT"});
break;
}
}
f = 1;
}
if (fy != ty)
{
for (auto &[id, x, y, z] : e[1])
{
if (x == fx && z == fz)
{
if (f) t ++;
int pos = get_pos(y, t, m);
t += get_t(pos, fy, m);
v[t].push_back({i, id, fx, fy, fz, "IN"});
t += get_t(fy, ty, m);
fy = ty;
v[t].push_back({i, id, fx, fy, fz, "OUT"});
break;
}
}
f = 1;
}
if (fz != tz)
{
for (auto &[id, x, y, z] : e[2])
{
if (y == fy && x == fx)
{
if (f) t ++;
int pos = get_pos(z, t, h);
t += get_t(pos, fz, h);
v[t].push_back({i, id, fx, fy, fz, "IN"});
t += get_t(fz, tz, h);
fz = tz;
v[t].push_back({i, id, fx, fy, fz, "OUT"});
break;
}
}
}
time = max(time, t);
}
for (int i = 1; i <= time; i ++ )
{
if (v[i].empty()) continue;
sort(v[i].begin(), v[i].end());
for (auto &[pi, ei, x, y, z, st] : v[i])
{
cout << "[" << i <<"s] Person " << pi << " " << st << " Elevator "
<< ei << " at (" << x << ", " << y << ", " << z <<")\n";
}
}
}
int main()
{
IOS; cin.tie(0); cout.tie(0);
//int T; cin >> T;
//while(T -- ) solve();
solve();
return 0;
}
J Mex Tree
int n, val[N];
int h[N], e[M], ne[M], idx;
int ans[N], sz[N], mn[N];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void dfs(int u, int fa)
{
sz[u] = 1, mn[u] = val[u];
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (j == fa) continue;
dfs(j, u);
sz[u] += sz[j];
mn[u] = min(mn[u], mn[j]);
}
}
void dfs1(int u, int fa)
{
if (val[u] != 0 && val[u] != n)
{
if (mn[u] == val[u])
ans[val[u]] = n - sz[u];
else ans[val[u]] = 0;
}
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (j == fa) continue;
dfs1(j, u);
}
}
void solve()
{
memset(h, -1, sizeof h);
cin >> n;
for (int i = 1; i <= n; i ++ ) cin >> val[i];
for (int i = 2; i <= n; i ++ )
{
int j; cin >> j;
add(i, j), add(j, i);
}
ans[n] = n;
int root;
for (int i = 1; i <= n; i ++ )
if (val[i] == 0)
{
root = i;
break;
}
dfs(root, -1);
for (int i = h[root]; ~i; i = ne[i])
{
int j = e[i];
ans[0] = max(ans[0], sz[j]);
}
dfs1(root, -1);
for (int i = 0; i <= n; i ++ ) cout << ans[i] << " ";
}
int main()
{
IOS; cin.tie(0); cout.tie(0);
//int T; cin >> T;
//while (T -- ) solve();
solve();
return 0;
}
K 复合函数
int h[N], e[N], ne[N], idx;
bool st[N], ins[N];
int fu[N], ed[N], cir[N], cnt, t;
int sum[500][N], mp1[N], mp2[N];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void dfs_c(int u)
{
st[u] = ins[u] = true;
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
fu[j] = u;
if (!st[j]) dfs_c(j);
else if (ins[j])
{
cnt ++;
ed[cnt] = ed[cnt - 1];
for (int k = u; k != j; k = fu[k])
cir[ ++ ed[cnt]] = k;
cir[ ++ ed[cnt]] = j;
}
}
ins[u] = false;
}
void dfs(int u, int dep, int tt)
{
sum[tt][dep] ++;
// cout << sz << " " << dep << " " << sum[sz][dep] << "\n";
st[u] = true;
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (st[j]) continue;
if (!st[j]) dfs(j, dep + 1, tt);
}
}
void solve()
{
memset(h, -1, sizeof h);
int n; cin >> n;
for (int i = 1; i <= n; i ++ )
{
int j; cin >> j;
add(j, i);
}
for (int i = 1; i <= n; i ++ )
if (!st[i])
dfs_c(i);
memset(st, false, sizeof st);
for (int i = 1; i <= ed[cnt]; i ++ ) st[cir[i]] = true;
for (int i = 1; i <= cnt; i ++ )
{
int sz = ed[i] - ed[i - 1];
if (!mp1[sz])
{
mp1[sz] = ++ t;
mp2[t] = sz;
}
for (int j = ed[i - 1] + 1; j <= ed[i]; j ++ )
{
int k = cir[j];
dfs(k, 0, mp1[sz]);
}
}
for (int i = 1; i <= t; i ++ )
for (int j = 1; j < N; j ++ )
sum[i][j] += sum[i][j - 1];
int m; cin >> m;
while (m -- )
{
LL a, b, ans = 0;
cin >> a >> b;
if (a == b)
{
cout << n << "\n";
continue;
}
if (a > b) swap(a, b);
for (int i = 1; i <= t; i ++ )
{
int sz = mp2[i];
// cout << sz << "\n";
if ((b - a) % sz == 0)
{
if (a < N) ans += sum[i][a];
else ans += sum[i][N - 1];
}
}
cout << ans << "\n";
}
}
int main()
{
IOS; cin.tie(0); cout.tie(0);
//int T; cin >> T;
//while(T -- ) solve();
solve();
return 0;
}