不会,二分 / 三分,期望 dp + 高斯消元
# A. 记事本
不会。
:建图跑最短路。
:分讨模拟。
放个 60 分的代码吧。
#include <bits/stdc++.h> | |
#define pb push_back | |
using namespace std; | |
namespace IO{ | |
inline int read(){ | |
int x = 0, f = 1; | |
char ch = getchar(); | |
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();} | |
while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); | |
return x * f; | |
} | |
template <typename T> inline void write(T x){ | |
if(x < 0) putchar('-'), x = -x; | |
if(x > 9) write(x / 10); | |
putchar(x % 10 + '0'); | |
} | |
} | |
using namespace IO; | |
const int N = 2010; | |
int n, q; | |
int a[N], pre[N], nxt[N]; | |
int mn[N][20]; | |
inline int qry(int l, int r){ | |
if(l >= r) return 1e9; | |
int k = log2(r - l + 1); | |
// cout << l << " " << r << " " << k << " " << r - (1 << k) + 1 << endl; | |
return min(mn[l][k], mn[r - (1 << k) + 1][k]); | |
} | |
signed main(){ | |
#ifndef ONLINE_JUDGE | |
freopen("test.in", "r", stdin); | |
freopen("test.out", "w", stdout); | |
#endif | |
n = read(); | |
for(int i = 1; i <= n; ++i) | |
a[i] = mn[i][0] = read(), pre[i] = nxt[i] = i; | |
for(int i = 2; i <= n; ++i) | |
if(a[i - 1] < a[i]) pre[i] = pre[i - 1]; | |
for(int i = n - 1; i >= 1; --i) | |
if(a[i + 1] < a[i]) nxt[i] = nxt[i + 1]; | |
for(int j = 1; j <= 19; ++j) | |
for(int i = 1; i + (1 << j) - 1 <= n; ++i) | |
mn[i][j] = min(mn[i][j - 1], mn[i + (1 << (j - 1))][j - 1]); | |
q = read(); | |
// for(int i = 44; i <= 58; ++i) cout << a[i] << " "; | |
// cout << endl; | |
while(q--){ | |
int r1 = read(), c1 = read(), r2 = read(), c2 = read(), cw = c1, ct = c1; | |
// if(abs(r1 - r2) <= 10) cout << "???" << endl; | |
int ans = 1e9; | |
if(r1 < r2){ | |
c1 = min(c1, qry(r1, r2)); | |
// for(int i = r1; i <= r2; ++i) c1 = min(c1, a[i]); | |
ans = r2 - r1 + min({abs(c1 - c2), c2 + (c1 != 0), a[r2] - c2 + (c1 != a[r2])}); | |
for(int i = r1; i <= r2; ++i){ | |
ct = min(ct, a[i]); | |
int flag = (ct != a[i]); | |
c1 = a[i]; | |
c1 = min(c1, qry(i + 1, r2)); | |
// for(int j = i + 1; j <= r2; ++j) c1 = min(c1, a[j]); | |
ans = min(ans, r2 - r1 + flag + abs(c1 - c2)); | |
} | |
for(int i = r2 + 1; i <= n; ++i){ | |
ct = min(ct, a[i]); | |
int flag = (ct != a[i]); | |
c1 = a[i]; | |
c1 = min(c1, qry(r2, i - 1)); | |
// for(int j = i - 1; j >= r2; --j) c1 = min(c1, a[j]); | |
ans = min(ans, i - r1 + i - r2 + abs(c1 - c2) + flag); | |
} | |
ct = cw; | |
for(int i = r1 - 1; i >= 1; --i){ | |
ct = min(ct, a[i]); | |
int flag = (ct != a[i]); | |
c1 = a[i]; | |
c1 = min(c1, qry(i + 1, r2)); | |
// for(int j = i + 1; j <= r2; ++j) c1 = min(c1, a[j]); | |
ans = min(ans, r2 - i + r1 - i + abs(c1 - c2) + flag); | |
} | |
write(ans), puts(""); | |
}else{ | |
c1 = min(c1, qry(r2, r1)); | |
// for(int i = r2; i <= r1; ++i) c1 = min(c1, a[i]); | |
ans = r1 - r2 + min({abs(c1 - c2), c2 + (c1 != 0), a[r2] - c2 + (c1 != a[r2])}); | |
c1 = cw; | |
for(int i = r1; i >= r2; --i){ | |
ct = min(ct, a[i]); | |
int flag = (ct != a[i]); | |
c1 = a[i]; | |
c1 = min(c1, qry(r2, i - 1)); | |
// for(int j = i - 1; j >= r2; --j) c1 = min(c1, a[j]); | |
ans = min(ans, r1 - r2 + flag + abs(c1 - c2)); | |
} | |
for(int i = r2 - 1; i >= 1; --i){ | |
ct = min(ct, a[i]); | |
int flag = (ct != a[i]); | |
c1 = a[i]; | |
c1 = min(c1, qry(i + 1, r2)); | |
// for(int j = i + 1; j <= r2; ++j) c1 = min(c1, a[j]); | |
ans = min(ans, r1 - i + r2 - i + abs(c1 - c2) + flag); | |
} | |
ct = cw; | |
for(int i = r1 + 1; i <= n; ++i){ | |
ct = min(ct, a[i]); | |
int flag = (ct != a[i]); | |
c1 = a[i]; | |
c1 = min(c1, qry(r2, i - 1)); | |
// for(int j = i - 1; j >= r2; --j) c1 = min(c1, a[j]); | |
ans = min(ans, i - r1 + i - r2 + abs(c1 - c2) + flag); | |
} | |
write(ans), puts(""); | |
} | |
} | |
return 0; | |
} |
# B. 子集
枚举中位数,二分选数个数,手动计算价值。
#include <bits/stdc++.h> | |
#define pb push_back | |
#define int long long | |
using namespace std; | |
namespace IO{ | |
inline int read(){ | |
int x = 0, f = 1; | |
char ch = getchar(); | |
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();} | |
while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); | |
return x * f; | |
} | |
template <typename T> inline void write(T x){ | |
if(x < 0) putchar('-'), x = -x; | |
if(x > 9) write(x / 10); | |
putchar(x % 10 + '0'); | |
} | |
} | |
using namespace IO; | |
const int N = 2e5 + 10; | |
int n; | |
int a[N], s[N]; | |
inline double calc(int x, int mid){ | |
int sum = s[x] - s[x - mid - 1] + s[n] - s[n - mid]; | |
return 1.0 * sum / (mid + mid + 1) - a[x]; | |
} | |
signed main(){ | |
#ifndef ONLINE_JUDGE | |
freopen("test.in", "r", stdin); | |
freopen("test.out", "w", stdout); | |
#endif | |
n = read(); | |
for(int i = 1; i <= n; ++i) a[i] = read(); | |
sort(a + 1, a + 1 + n); | |
for(int i = 1; i <= n; ++i) s[i] = s[i - 1] + a[i]; | |
double ans = 0; | |
if(n <= 2000){ | |
for(int i = 1; i <= n; ++i){ | |
int l = i - 1, r = n, sum = a[i], cnt = 1; | |
while(l >= 1 && r > i){ | |
sum += a[l] + a[r]; | |
l--, r--, cnt += 2; | |
ans = max(ans, 1.0 * sum / cnt - a[i]); | |
} | |
} | |
}else{ | |
for(int i = 1; i <= n; ++i){ | |
int l = 0, r = min(i - 1, n - i); | |
while(l <= r){ | |
int mid = (l + r) >> 1; | |
// cout << l << " " << r << " " << midl << " " << midr << endl; | |
if(calc(i, mid) > calc(i, mid - 1)) l = mid + 1; | |
else r = mid - 1; | |
} | |
ans = max(ans, calc(i, r)); | |
// ans = max({ans, calc(i, l), calc(i, r)}); | |
} | |
} | |
printf("%.5lf\n", ans); | |
return 0; | |
} |
# C. 子串
先建出 AC 自动机,设 表示到达 AC 自动机上 点时期望再加上多少个点结束。
那么有 。
设 是 AC 自动机上 的子节点,有转移:
根据这个式子建出方程组,然后高斯消元即可。
#include <bits/stdc++.h> | |
#define pb push_back | |
using namespace std; | |
namespace IO{ | |
inline int read(){ | |
int x = 0, f = 1; | |
char ch = getchar(); | |
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();} | |
while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); | |
return x * f; | |
} | |
template <typename T> inline void write(T x){ | |
if(x < 0) putchar('-'), x = -x; | |
if(x > 9) write(x / 10); | |
putchar(x % 10 + '0'); | |
} | |
} | |
using namespace IO; | |
const int N = 200; | |
const int mod = 1e9 + 7; | |
int T, n, inv26; | |
char s[N]; | |
inline int add(int x) {return x >= mod ? x - mod : x;} | |
inline int sub(int x) {return x < 0 ? x + mod : x;} | |
inline int mul(int x, int y) {return 1ll * x * y % mod;} | |
inline int qpow(int a, int b){ | |
int res = 1; | |
while(b){ | |
if(b & 1) res = mul(res, a); | |
a = mul(a, a), b >>= 1; | |
} | |
return res; | |
} | |
int ch[N][26], tot, End[N]; | |
int fail[N]; | |
inline void insert(char *s){ | |
int len = strlen(s), now = 0; | |
for(int i = 0; i < len; ++i){ | |
int c = s[i] - 'a'; | |
if(!ch[now][c]) ch[now][c] = ++tot; | |
now = ch[now][c]; | |
} | |
End[now] = 1; | |
} | |
inline void build(){ | |
queue <int> q; | |
for(int i = 0; i < 26; ++i) | |
if(ch[0][i]) q.push(ch[0][i]); | |
while(!q.empty()){ | |
int x = q.front(); q.pop(); | |
for(int i = 0; i < 26; ++i){ | |
if(ch[x][i]) fail[ch[x][i]] = ch[fail[x]][i], q.push(ch[x][i]); | |
else ch[x][i] = ch[fail[x]][i]; | |
} | |
} | |
} | |
int a[N][N]; | |
inline void Gauss(int n){ | |
for(int i = 0; i <= n; ++i){ | |
for(int j = i + 1; j <= n && a[i][i] == 0; ++j) | |
if(a[j][i]) swap(a[i], a[j]); | |
int inv = qpow(a[i][i], mod - 2); | |
for(int j = i + 1; j <= n; ++j) | |
for(int k = n + 1; k >= i; --k) | |
a[j][k] = sub(a[j][k] - mul(a[i][k], mul(a[j][i], inv))); | |
} | |
for(int i = n; i >= 0; --i){ | |
for(int j = i + 1; j <= n; ++j) | |
a[i][n + 1] = sub(a[i][n + 1] - mul(a[i][j], a[j][n + 1])); | |
a[i][n + 1] = mul(a[i][n + 1], qpow(a[i][i], mod - 2)); | |
} | |
} | |
inline void solve(){ | |
tot = 0; | |
memset(a, 0, sizeof(a)); | |
memset(ch, 0, sizeof(ch)); | |
memset(End, 0, sizeof(End)); | |
memset(fail, 0, sizeof(fail)); | |
n = read(); | |
for(int i = 1; i <= n; ++i) | |
scanf("%s", s), insert(s); | |
build(); | |
for(int i = 0; i <= tot; ++i){ | |
a[i][i] = 1; | |
if(End[i]) continue; | |
a[i][tot + 1] = 1; | |
for(int j = 0; j < 26; ++j) | |
a[i][ch[i][j]] = sub(a[i][ch[i][j]] - inv26); | |
} | |
Gauss(tot); | |
write(a[0][tot + 1]), puts(""); | |
} | |
signed main(){ | |
#ifndef ONLINE_JUDGE | |
freopen("test.in", "r", stdin); | |
freopen("test.out", "w", stdout); | |
#endif | |
T = read(), inv26 = qpow(26, mod - 2); | |
while(T--) solve(); | |
return 0; | |
} |