CF 915G Coprime Arrays

题目描述

https://codeforces.com/contest/915/problem/G

Solution

$b_m=\sum_{i_1=1}^m\sum_{i_2=1}^m\cdots\sum_{i_n=1}^m[(i_1,i_2,\cdots,i_n)=1]$

我们套路化简得到

$b_m=\sum_{d=1}^m\mu(d)\sum_{d|i_1}\sum_{d|i_2}\cdots\sum_{d|i_n}1=\sum_{d=1}^m\mu(d){\lfloor\frac md\rfloor}^n$

如果我们预处理 $n$ 次幂,那么枚举 $m$ 能够做到 $O(n\sqrt n)$,但是这不足以通过此题

我们考虑枚举 $d$,注意到 ${\lfloor\frac md\rfloor}^n$ 对连续 $d$ 个数是相同的,那么这样做的复杂度就是 $O(k\log k)$

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
#include <iostream>
#include <vector>
#define maxn 2000010
#define ll long long
using namespace std;

const int p = 1000000007;

ll pow_mod(ll x, ll n) {
ll s = 1;
for (; n; n >>= 1, x = x * x % p)
if (n & 1) s = s * x % p;
return s;
}

int n, k;

int pri[maxn], cnt, mu[maxn]; bool isp[maxn];
void init_isp(int n) {
mu[1] = 1;
for (int i = 2; i <= n; ++i) {
if (!isp[i]) pri[++cnt] = i, mu[i] = -1;
for (int j = 1; j <= cnt && i * pri[j] <= n; ++j) {
isp[i * pri[j]] = 1;
if (i % pri[j] == 0) break;
mu[i * pri[j]] = -mu[i];
}
}
}

ll s[maxn], _pow[maxn];

int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);

cin >> n >> k; init_isp(k);
for (int i = 1; i <= k; ++i) _pow[i] = pow_mod(i, n);
for (int i = 1; i <= k; ++i)
for (int j = i; j <= k; j += i) {
s[j] = (s[j] + mu[i] * _pow[j / i]) % p;
if (j + i <= k) s[j + i] = (s[j + i] - mu[i] * _pow[j / i]) % p;
}
ll ans = 0;
for (int i = 1; i <= k; ++i) {
s[i] = (s[i] + s[i - 1]) % p;
ans = (ans + ((s[i] + p) % p ^ i)) % p;
} cout << ans << "\n";
return 0;
}