【题解】【化学】实验
原题链接
题意:
给
首先,
按照题目描述里说的,如果定义
可以看出这玩意也就等于
另一个问题是求
再换句话,如果
这样的描述可以转化为图论模型:每种液体是一个节点,如果
举个例子,当
于是我们就有了最暴力的算法:对于每个
不过,我们发现,这张图里很多点实际都是没有用的。所有
另一方面,对于
可以考虑按照
但是这样复杂度是
可以考虑从
注意到如果使用线性筛,本题的内存非常的卡,所以我做了一些卡内存的小优化:把
完整代码
#include <cstdio>
#include <vector>
#define N 200000
#define M 20000001
#define R 201
#define L 40001
std::vector<int> pr;
int s[M], h[L]; char st[M];
void prime() {
for (int i = 2; i < M; i++) {
if (!s[i]) {
pr.push_back(i);
s[i] = i;
st[i] = 1;
if (i < L) h[i] = 1;
}
for (int j : pr) {
if (i*j >= M) break;
s[i*j] = j;
st[i*j] = (s[i] == j) ? st[i]+1 : 1;
if (i*j < L) h[i*j] = (s[i] == j && st[i] & 1) ? h[i]*j : h[i];
if (i % j == 0) break;
}
}
for (int i = 2; i < M; i++) {
for (int j : pr) {
if (i*j >= M) break;
st[i*j] = std::max(st[i], st[i*j]);
if (i % j == 0) break;
}
}
}
struct pair {int x, y; };
pair operator + (pair a, pair b) {
return (pair) {a.x + b.x, a.y + b.y};
}
int n, m, a[N], b[N], mv[R], f[R], p[R];
pair co[R], ans[R], cnt;
int fa(int x) {
return x == f[x] ? x : f[x] = fa(f[x]);
}
int main() {
prime();
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++)
scanf("%d", a+i);
for (int i = 0; i < n; i++) {
scanf("%d", b+i);
a[i] = h[a[i]];
b[i] = st[b[i]];
co[a[i]] = co[a[i]] + (pair) {1, b[i]};
mv[a[i]] = std::max(mv[a[i]], b[i]);
}
for (int i = 2; i < R; i++)
co[i] = co[i] + co[i-1];
for (int i = R-1; i >= 2; i--) {
ans[i] = co[i]+cnt;
bool mg = false;
f[i] = i; p[i] = mv[i];
cnt = cnt + (pair) {1, mv[i]};
for (int j = 2; i*j < R; j++) if (mv[i*j]) {
int x = fa(i), y = fa(i*j);
if (x != y) {
mg = true;
f[x] = y;
cnt.x--;
cnt.y -= std::min(p[x], p[y]);
p[y] = std::max(p[x], p[y]);
}
}
if (!mv[i] && !mg) cnt.x--;
}
while (m--) {
int x; scanf("%d", &x);
pair p = (x < R) ? ans[x] : co[R-1];
printf("%d %d\n", p.x, p.y);
}
}