Convolution
定义 a ⊕ b = a × b gcd ( a , b ) 2 a \oplus b = \frac{a \times b}{\gcd(a, b) ^ 2} a⊕b=gcd(a,b)2a×b, b m = ∑ i = 1 n ∑ j = 1 n a i × j c [ i ⊕ j = m ] b_m = \sum\limits_{i = 1} ^{n} \sum\limits_{j = 1} ^{n}a_i \times j ^ c [i \oplus j = m] bm=i=1∑nj=1∑nai×jc[i⊕j=m],我们要求 b 1 ⊕ b 2 ⊕ ⋯ ⊕ b n b_1 \oplus b_2 \oplus \dots \oplus b_n b1⊕b2⊕⋯⊕bn。
因为
a
⊕
b
a \oplus b
a⊕b的性质,我们可以考虑枚举
a
gcd
(
a
,
b
)
,
b
gcd
(
a
,
b
)
\frac{a}{\gcd(a, b)}, \frac{b}{\gcd(a, b)}
gcd(a,b)a,gcd(a,b)b,设其为
a
′
,
b
′
a', b'
a′,b′,则有
gcd
(
a
′
,
b
′
)
\gcd(a', b')
gcd(a′,b′)互质,
b
m
=
∑
i
=
1
n
∑
j
=
1
n
[
i
×
j
=
m
gcd
(
i
,
j
)
=
1
]
∑
d
=
1
m
i
n
(
n
i
,
n
j
)
(
a
i
d
(
j
d
)
c
)
∑
i
=
1
n
∑
j
=
1
n
[
i
×
j
=
m
gcd
(
i
,
j
)
=
1
]
j
c
∑
d
=
1
m
i
n
(
n
i
,
n
j
)
a
i
d
d
c
设
f
(
i
,
n
)
=
∑
d
=
1
n
a
i
d
d
c
b_m = \sum_{i = 1} ^{n} \sum_{j = 1} ^{n}[i \times j = m\ \gcd(i, j) = 1] \sum_{d = 1} ^{min(\frac{n}{i}, \frac{n}{j})} (a_{id} (jd) ^ c)\\ \sum_{i = 1} ^{n} \sum_{j = 1} ^{n} [i \times j = m \ \gcd(i, j) = 1] j ^ c \sum_{d = 1} ^{min(\frac{n}{i}, \frac{n}{j})} a_{id} d ^ c\\ 设f(i, n) = \sum_{d = 1} ^{n} a_{id} d ^ c\\
bm=i=1∑nj=1∑n[i×j=m gcd(i,j)=1]d=1∑min(in,jn)(aid(jd)c)i=1∑nj=1∑n[i×j=m gcd(i,j)=1]jcd=1∑min(in,jn)aiddc设f(i,n)=d=1∑naiddc
容易发现
m
i
n
(
n
i
,
n
j
)
min(\frac{n}{i}, \frac{n}{j})
min(in,jn),如果考虑枚举
i
i
i,则可以直接处理出
f
(
i
,
n
)
f(i, n)
f(i,n),而且整体复杂度还是不变的。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10, mod = 998244353;
int prime[N], phi[N], f[N], ans[N], a[N], p[N], n, c, cnt;
bool st[N];
inline int add(int x, int y) {
return x + y < mod ? x + y : x + y - mod;
}
inline int sub(int x, int y) {
return x >= y ? x - y : x - y + mod;
}
int quick_pow(int a, int n) {
int ans = 1;
while (n) {
if (n & 1) {
ans = 1ll * ans * a % mod;
}
a = 1ll * a * a % mod;
n >>= 1;
}
return ans;
}
void init() {
phi[1] = p[1] = 1;
for (int i = 2; i < N; i++) {
if (!st[i]) {
prime[++cnt] = i;
phi[i] = i - 1;
p[i] = quick_pow(i, c);
}
for (int j = 1; j <= cnt && 1ll * i * prime[j] < N; j++) {
st[i * prime[j]] = 1, p[i * prime[j]] = 1ll * p[i] * p[prime[j]] % mod;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
scanf("%d %d", &n, &c);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
init();
for (int i = 1; i <= n; i++) {
for (int j = 1; i * j <= n; j++) {
f[j] = add(f[j - 1], 1ll * a[i * j] * p[j] % mod);
}
for (int j = 1; i * j <= n; j++) {
if (phi[i] * phi[j] == phi[i * j]) {
ans[i * j] = add(ans[i * j], 1ll * p[j] * f[min(n / i, n / j)] % mod);
}
}
}
int res = 0;
for (int i = 1; i <= n; i++) {
res ^= ans[i];
}
printf("%d\n", res);
return 0;
}