题解:CF547C Mike and Foam
CF547C
题意
给定一个长度为
每次操作后输出取出的数字中满足
思路
假设当前需要取出
设之前已被取出的数共
那么
考虑对式子进行变换,有
对于
所以可以考虑只枚举满足
因此,将
由于
之后直接枚举这
对于枚举的每一个
由于
放回
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10, M = 5e5 + 10;
int n, q, a[N], c[M], ct;
long long cnt;
bool f[N];
int main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> q;
for (int i = 1; i <= n; i++) cin >> a[i];
while (q--) {
int x; cin >> x;
int tmp = a[x];
vector<int> pr;
for (int i = 2; i * i <= tmp; i++) {
bool flag = 0;
while (tmp % i == 0) flag = 1, tmp /= i;
if (flag) pr.push_back(i);
}
if (tmp != 1) pr.push_back(tmp);
if (!f[x]) {
cnt += ct, ct++;
for (int i = 1; i < (1 << pr.size()); i++) {
int val = 1, k = 1;
for (int j = 0; j < pr.size(); j++) {
if (i & (1 << j)) val *= -1, k *= pr[j];
}
cnt += val * c[k], c[k]++;
}
} else {
ct--, cnt -= ct;
for (int i = 1; i < (1 << pr.size()); i++) {
int val = 1, k = 1;
for (int j = 0; j < pr.size(); j++) {
if (i & (1 << j)) val *= -1, k *= pr[j];
}
c[k]--, cnt -= val * c[k];
}
}
cout << cnt << '\n';
f[x] ^= 1;
}
return 0;
}