Convolution
定义a⊕b=a×bgcd(a,b)2a \oplus b = \frac{a \times b}{\gcd(a, b) ^ 2}a⊕b=gcd(a,b)2a×b,bm=∑i=1n∑j=1nai×jc[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],我们要求b1⊕b2⊕⋯⊕bnb_1 \oplus b_2 \oplus \dots \oplus b_nb1⊕b2⊕⋯⊕bn。
因为a⊕ba \oplus ba⊕b的性质,我们可以考虑枚举agcd(a,b),bgcd(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′)互质,
bm=∑i=1n∑j=1n[i×j=mgcd(i,j)=1]∑d=1min(ni,nj)(aid(jd)c)∑i=1n∑j=1n[i×j=mgcd(i,j)=1]jc∑d=1min(ni,nj)aiddc设f(i,n)=∑d=1naiddcb_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
容易发现min(ni,nj)min(\frac{n}{i}, \frac{n}{j})min(in,jn),如果考虑枚举iii,则可以直接处理出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;
}