[PKUPC2019E]Coprime 题解

把$\Theta(nlog^2n)$的复杂度算成$\Theta(n^2)$的后果…
我要向全队人民谢罪

先推一步式子:

然后我一看:这玩意复杂度比暴力还高…不会做了
事实上对于$[1,100000]$中的任意一个整数,它的因子个数大概是log级别的。所以,后面那个东西可以通过vector+二分得到。
所以这玩意复杂度实际上是双log的,暴力模拟即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <bits/stdc++.h>
#define dbg(x) std::cerr << #x << " = " << x << "\n"
using namespace std;
typedef long long ll;

const int N = 100000 + 10;
int t, n, m, a[N];
int mu[N], prime[N], np[N], cnt, smallest[N];

void pre() {
np[1] = mu[1] = 1;
for(int i = 2; i <= 100000; i++) {
if(!np[i]) prime[++cnt] = i, mu[i] = -1, smallest[i] = i;
for(int j = 1; j <= cnt && i * prime[j] <= 100000; j++) {
np[i * prime[j]] = 1; smallest[i * prime[j]] = prime[j];
if(i % prime[j] == 0) {mu[i * prime[j]] = 0;break;}
else mu[i * prime[j]] = -mu[i];
}
}
}
vector <int> divisior, v;
vector <int> pool[N];
int cont[N];
int sz, ans;

int bs(int id, int x) {
if(pool[id].size() == 0) return 0;
if(pool[id][(int)pool[id].size() - 1] < x) return pool[id].size();
if(pool[id][0] >= x) return 0;
int l = 0, r = (int)(pool[id].size()) - 1, ans = 0;
while(l <= r) {
int mid = (l + r) >> 1;
if(pool[id][mid] < x) ans = mid, l = mid + 1;
else r = mid - 1;
}
return ans + 1;
}
int query(int id, int l, int r) {
int ans = min(bs(id, r + 1) - bs(id, l), (int)pool[id].size());
return ans;
}
void dfs(int cur, int d) {
if(cur == sz) {
if(!cont[d]) cont[d] = true, v.push_back(d);
return ;
}
dfs(cur + 1, d * divisior[cur]);
dfs(cur + 1, d);
}

void dfs2(int cur, int d, int l, int r) {
if(cur == sz) {
if(!cont[d]) cont[d] = 1, v.push_back(d), ans += mu[d] * query(d, l, r);
return ;
}
dfs2(cur + 1, d * divisior[cur], l, r);
dfs2(cur + 1, d , l, r);
}
void solve() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
for(int i = 1; i <= 100000; i++) pool[i].clear();
for(int i = 1; i <= n; i++) {
v.clear(); divisior.clear(); int cp = a[i];
while(cp != 1) {
divisior.push_back(smallest[cp]);
cp /= smallest[cp];
}
sz = divisior.size(); dfs(0, 1);
for(int j = 0; j < v.size(); j++) {
pool[v[j]].push_back(i); cont[v[j]] = 0;
}
}

int d = 0;
while(m--) {
int l, r, x; scanf("%d%d%d", &l, &r, &x);

l ^= d, r ^= d, x ^= d;
int curx = x; ans = 0;
divisior.clear(); v.clear();
while(curx != 1) {
divisior.push_back(smallest[curx]);
curx /= smallest[curx];
}
sz = divisior.size();
dfs2(0, 1, l, r);
d = ans;
printf("%d\n", d);
for(int j = 0; j < v.size(); j++) cont[v[j]] = 0;
}
for(int i = 0; i < v.size(); i++) cont[v[i]] = 0;
}
int main() {
scanf("%d", &t);
pre();
while(t--) solve();
return 0;
}
# 数论

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×