目录
D. Sum of XOR Functions:
题目大意:
思路解析:
统计区间 [L,R]的异或值,其实我们看作枚举每个二进制位,看哪些区间在这个二进制位上有答案贡献,那么1 - i在当前位异或值为0时,那么他与前面 1-k在这位异或值不为0的点k,可以组成区间[K+1,i],这个区间对于答案是有贡献的。如果当前位异或值为1,那么就可以前面异或值为0的点组成区间。
又因为它要乘以一个区间的长度,那么如果在1-i位可以组成三个区间,那么长度就为 (3*i) - (k1+k2+k3) ,这就是三个区间的总长度,然后枚举i,就可以算出在这一个二进位上的所有答案区间的长度,利用长度乘以这个二进制位的贡献即可。
那么这样也就实现了对答案的统计。
代码实现:
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main {
static long inf = (long) 2e18;
static long mod = 998244353;
public static void main(String[] args) throws IOException {
int t = 1;
while (t > 0) {
solve();
t--;
}
w.flush();
w.close();
br.close();
}
public static void solve() {
int n = f.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = f.nextInt();
}
long ans = 0;
for (int b = 0; b < 30; b++) {
int[] cnt = new int[2];
long[] sumOfL = new long[2];
int x = 0;
cnt[0] = 1;
long cur = 0;
for (int i = 0; i < n; i++) {
x ^= ((a[i] >> b) & 1);
long sumR = (long) (i + 1) * cnt[x ^ 1] % mod;
cur = (cur + ((sumR - sumOfL[x ^ 1]) % mod + mod) % mod) % mod;
++cnt[x];
sumOfL[x] = (sumOfL[x] + i + 1) % mod;
}
ans = (ans + (cur * (1 << b)) % mod) % mod;
}
w.println(ans);
}
static long qkm(long a){
long b = mod - 2;
long res = 1;
while (b > 0){
if ((b & 1) == 1) res = (res * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return res;
}
static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
static Input f = new Input(System.in);
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static class Input {
public BufferedReader reader;
public StringTokenizer tokenizer;
public Input(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public String nextLine() {
String str = null;
try {
str = reader.readLine();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return str;
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public Double nextDouble() {
return Double.parseDouble(next());
}
public BigInteger nextBigInteger() {
return new BigInteger(next());
}
}
}