A
枚举倍数就行了
然后挨个去查找, 调和级数nlogn,
这就是好多人这样过的, 这是数据水了....
毕竟 n 是 1e7, 这是卡爆他们的数据
100000
1, 2, ..., 9999, 10000000
大概需要计算1e8+(还不算循环里的两条指令), 再好的评侧鸡也不能跑到 1e8+ 吧..
所以我们应注意到, 在累加 i 的时候会重复, 枚举素数倍就好了, 复杂度就成了 nloglogn, 2e7+
const int N = 1e7 + 5;
int n, m, _, k;
ll a[N], b[N], d[N];
int prime[N], tot;
bool v[N];
void init(int n) {
rep (i, 2, n) {
if (!v[i]) prime[++tot] = i;
for (int j = 1; prime[j] <= n / i && j <= tot; ++j) {
v[prime[j] * i] = 1;
if (i % prime[j] == 0) break;
}
}
}
int main() {
IOS; cin >> n; init(1e7);
rep (i, 1, n) cin >> a[i], ++b[a[i]];
ll ans = 0;
per (i, 1e7, 1) {
for (int j = 1; prime[j] <= 1e7 / i; ++j) umax(d[i], d[prime[j] * i]);
umax(ans, d[i] += b[i]);
}
cout << ans;
return 0;
}
B
对每个点能到的点(即 x 到 y 的直线路径上没 墙 )建边, 跑最短路
怎么判线段相交就不贴了, 板子太长, 用你自己的几何板子就行了
int n, m, k, _;
int h[N], ne[M << 1], to[M << 1], tot;
double co[M << 1], dis[N];
bool v[N];
void add(int u, int v, double c) {
ne[++tot] = h[u]; to[h[u] = tot] = v; co[tot] = c;
ne[++tot] = h[v]; to[h[v] = tot] = u; co[tot] = c;
}
int main() {
IOS; cin >> n >> m >> k;
rep (i, 0, k) pos[i << 1].in(), pos[i << 1 | 1].in();
rep (i, 0, (k << 1) + 1) {
dis[i] = 2e9;
rep (j, i + 1, (k << 1) + 1) {
bool f = 1;
rep (_, 0, k - 1)
if (pan_cross_LL(pos[i], pos[j], pos[_ << 1], pos[_ << 1 | 1])) f = 0;
if (f) add(i, j, Len(pos[i] - pos[j]));
}
}
priority_queue<pair<double, int>> q; q.push({ 0, k << 1}); dis[k << 1] = 0;
while (!q.empty()) {
int x = q.top().se; q.pop();
if (v[x]) continue; v[x] = 1;
for (int i = h[x]; i; i = ne[i]) {
int y = to[i]; double w = dis[x] + co[i];
if (w >= dis[y]) continue;
dis[y] = w; q.push({ -w, y });
}
}
cout << setiosflags(ios::fixed) << setprecision(4) << dis[k << 1 | 1];
return 0;
}
C
题意模拟,签到题
int main() {
IOS; string s;
cin >> s; ll cnt = 0;
rep (i, 0, s.size() - 1) {
if (s[i] == 'w') ++cnt;
if (!i || s[i] == 'v') continue;
if (s[i] != 'w') continue;
if (s[i - 1] == 'w') ++cnt;
}
cout << cnt;
return 0;
}
D
tarjan板子题, 板子就不贴, 其他专栏贴过
int main() {
IOS; cin >> n >> m;
tot = 1; totc = df = 0;
rep(i, 1, n) h[i] = dfn[i] = cut[i] = 0;
rep(i, 1, m) {
int u, v; cin >> u >> v;
add(u, v); add(v, u);
}
int sum = 0;
rep(i, 1, n) if (!dfn[i]) root = i, tarjan(i), ++sum;
rep(i, 1, n) cout << sum + cut[i] << ' ';
return 0;
}
F
二分就行, 记得 m * L 的地方可能爆ll, 用__int128
ll r[N], l[N], L, R, a[N];
bool check(__int128 m) {
ll cur = 0, res = 0;
rep(i, 1, n) {
ll c = a[i] / m;
if (c < l[i]) return 0;
umin(c, r[i]); cur += c * m;
if (c == r[i]) continue;
res += a[i] % m;
}
if (cur + res >= m * L) return 1;
return 0;
}
int main() {
IOS; cin >> n >> L >> R;
ll mx = 0, mi = 0, s = 0;
rep(i, 1, n) cin >> a[i], s += a[i];
rep(i, 1, n)
cin >> l[i] >> r[i], mi += l[i], mx += r[i];
if (mi > R || mx < L) { cout << 0; return 0; }
ll l = 0, r = s;
while (l < r) {
ll mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
cout << l;
return 0;
}
I
搜索low爆了
你在每个点走的方向唯一的, 那直接将 这个点和将要走到的点合并不好吗?
对环打标记
最后父亲等于自己的 且没有标记的, 是能走出去的点, 答案就是这些点和这些点的孩子的个数
int get(int x, int y) {
return (x - 1) * m + y;
}
int main() {
IOS; cin >> n >> m;
rep(i, 1, n) rep(j, 1, m) k = get(i, j), f[k] = k, siz[k] = 1;
rep(i, 1, n) {
cin >> s[i] + 1;
rep(j, 1, m)
if (s[i][j] == 'S') { if (i + 1 <= n) unit(get(i + 1, j), get(i, j)); }
else if (s[i][j] == 'W') { if (i - 1 > 0) unit(get(i - 1, j), get(i, j)); }
else if (s[i][j] == 'A') { if (j - 1 > 0) unit(get(i, j - 1), get(i, j)); }
else { if (j + 1 <= m) unit(get(i, j + 1), get(i, j)); }
}
int ans = 0;
rep(i, 1, n) rep(j, 1, m) {
int id = get(i, j);
if (f[id] != id || v[id]) continue;
ans += siz[id];
}
cout << ans;
return 0;
}
J
和开关问题一样, 还比他简单, 直接从 (1, 1) 开始改, 当无法改的的时候 不为0 就 QAQ
主要是裸一个二维区间查询和修改的数据结构, 线段树和树状数组都行, 我用的树状(代码短)
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n >> m >> x >> y;
rep(i, 1, n) rep(j, 1, m) {
cin >> a[i][j];
c[0][i][j] = c[1][i][j] = c[2][i][j] = c[3][i][j] = 0; //树状数组的初始化
}
bool f = 1;
rep(i, 1, n - x + 1) {
if (!f) break;
rep(j, 1, m - y + 1) {
int cur = a[i][j] + ask(i, j, i, j);
if (cur < 0) { f = 0; break; }
if (cur == 0) continue;
add(i, j, i + x - 1, j + y - 1, -cur);
}
rep(j, m - y + 2, m) {
int cur = a[i][j] + ask(i, j, i, j);
if (cur != 0) { f = 0; break; }
}
}
rep(i, n - x + 2, n) {
if (!f) break;
rep(j, 1, m) {
int cur = a[i][j] + ask(i, j, i, j);
if (cur != 0) { f = 0; break; }
}
}
if (f) cout << "^_^\n";
else cout << "QAQ\n";
}
return 0;
}