牛客练习赛74
这次我是真的nt, 1h前四题, 之后一直发呆
看出来了E是弗洛伊德, 怎么也调不出来, 比赛结束一看
我的三重循环的第三重是错的, 还是理解不够, 对这些小算法还是理解有点偏差,
明明应该是 rep(j, 1, n) 被我硬是写成了 rep(j, i + 1, n) 这怎么可能跑出多源最短路呢?
我是sb, 不然能进前十的, 艹
A CCA的数列
签到没啥好说的
int main() {
IOS; cin >> n;
rep (i, 1, n) cin >> a[i];
bool f = 1, g = 1, h = 1;
rep (i, 3, n) {
if (a[i] - a[i - 1] != a[2] - a[1]) f = 0;
if (a[i] * 1.0 / a[i - 1] != a[2] * 1.0 / a[1]) g = 0;
if (a[i] % a[i - 1] != a[2] % a[1]) h = 0;
}
if (f || g || h) cout << "YES
";
else cout << "NO
";
return 0;
}
B CCA的字符串
也是签到, 没啥好说的, 每次找到一个NowCoder, 就算一下贡献就好
char s[N], t[N] = "NowCoder";
bool check(char *s) {
rep (i, 0, 7) if (s[i] != t[i]) return 0;
return 1;
}
int main() {
IOS; cin >> s;
ll ans = 0, ls = 0, len = strlen(s);
for (int i = 0; s[i]; ++i) {
if (!check(s + i)) continue;
ans += (i - ls + 1ll) * (len - i - 7); ls = i + 1;
}
cout << ans;
return 0;
}
C CCA的矩阵
把矩阵转换一下, 变成他题目给定的矩阵即可, 给出转移方程
在原矩阵(a, b) 对应转换的矩阵 (a - b + n, a + b - 1)
剩下的就是跑个二位前缀和, 在特判在原矩阵上会不会锤子敲出界就好了
ll a[N][N];
int main() {
IOS; cin >> n >> k; m = k; k = (k << 1) - 1; int nn = (n << 1) - 1;
rep(i, 1, n) rep(j, 1, n) cin >> a[i - j + n][i + j - 1];
per(i, nn, 1) per(j, nn, 1) a[i][j] += a[i + 1][j] + a[i][j + 1] - a[i + 1][j + 1];
ll ans = 0;
rep(i, 1, nn) rep(j, 1, nn) {
if (i + j + 1 - n & 1) continue;
int x = i + j + 1 - n >> 1, y = j + 1 - x;
if (x > n - k + 1 || y < m || y > n - m + 1 || x < 1) continue;
umax(ans, a[i][j] - a[i + k][j] - a[i][j + k] + a[i + k][j + k]);
}
cout << ans;
return 0;
}
D CCA的图
先跑一次最大生成树, 记录第一次让 s, t合并的边的权值L,
再跑一遍最小生成树(生成边必须 >= L), 记录第一次让s, t合并的边的权值R
int s, t, f[N];
vector<pair<int, PII>> e;
int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); }
int kruskal(int k) {
rep (i, 1, n) f[i] = i;
for (auto &i : e) {
if (i.fi < k) continue;
int x = find(i.se.fi), y = find(i.se.se);
if (x == y) continue;
f[y] = x; x = find(s), y = find(t);
if (x == y) return i.fi;
}
return -1;
}
int main() {
IOS; cin >> n >> m >> s >> t;
rep (i, 1, m) {
int u, v, w; cin >> u >> v >> w;
e.pb({ w, { u, v }});
}
sort(all(e), [&](pair<int, PII>& a, pair<int, PII>& b) {
return a.fi > b.fi;
});
int L = kruskal(-2e9);
sort(all(e), [&](pair<int, PII>& a, pair<int, PII>& b) {
return a.fi < b.fi;
});
int R = kruskal(L);
cout << L << ' ' << R;
return 0;
}
E CCA的期望
统计一下每个点作为点对最短路上的节点的次数即可, md, 对弗洛伊德的理解还是不够
int b[N];
ll d[N][N], cnt[N];
ll qpow(ll a, ll b) {
ll ans = 1;
for (; b; b >>= 1, a = a * a % mod)
if (b & 1) ans = ans * a % mod;
return ans;
}
int main() {
IOS; cin >> n >> m >> k;
rep(i, 1, n) cin >> b[i];
memset(d, 0x3f, sizeof d);
rep(i, 1, m) {
int u, v, c; cin >> u >> v >> c;
d[u][v] = d[v][u] = min(d[v][u], (ll)c);
}
rep(i, 1, n) d[i][i] = 0;
rep(o, 1, n) rep(i, 1, n) rep(j, 1, n) umin(d[i][j], d[i][o] + d[o][j]);
rep(o, 1, n) rep(i, 1, n) rep(j, i + 1, n)
if (d[i][o] + d[o][j] == d[i][j]) ++cnt[o];
ll ans = 0, r = n * (n - 1) >> 1, p = qpow(r, mod - 2);
rep(i, 1, n)
if (b[i] || cnt[i] == r) ans = (ans + 1) % mod;
else {
ll q = (r - cnt[i]) * p % mod;
ans = (ans + 1 - qpow(q, k) + mod) % mod;
}
cout << ans;
return 0;
}