D. Sum of XOR Functions

D. Sum of XOR Functions

You are given an array a of length n consisting of non-negative integers.

You have to calculate the value of l=1nr=lnf(l,r)(rl+1), where f(l,r) is alal+1ar1ar (the character denotes bitwise XOR).

Since the answer can be very large, print it modulo 998244353.

Input

The first line contains one integer n (1n3105) — the length of the array a.

The second line contains n integers a1,a2,,an (0ai109).

Output

Print the one integer — the value of l=1nr=lnf(l,r)(rl+1), taken modulo 998244353.

Examples

Input

3
1 3 2

Output

12

Input

4
39 68 31 80

Output

1337

Input

7
313539461 779847196 221612534 488613315 633203958 394620685 761188160

Output

257421502

Note

In the first example, the answer is equal to f(1,1)+2f(1,2)+3f(1,3)+f(2,2)+2f(2,3)+f(3,3)= =1+22+30+3+21+2=12.

 

解题思路

  如果涉及到位运算的话一般都是按位来考虑,并且每一位的计算是相互独立的。对于 f(l,r)(rl+1),我们把 f(l,r) 看成是二进制转十进制的形式,例如有 26=(11010)2=24+23+21。由于 ai 的最大取值是 109,因此在二进制下最多有 30 位,在按位的考虑的思想下,l=1nr=lnf(l,r)(rl+1) 的结果可以看成是 20x0+21x1++229x29 的形式,其中 xk 表示考虑每个 ai 的第 k 位时 l=1nr=lnfk(l,r)(rl+1) 的结果,有 fk(l,r)=al,kal+1,kar1,kar,kai,k 表示 ai 在二进制下第 k 位的数值。

  当我们考虑按位计算是,本质上是处理由 a1,k,a2,k,,an,k 构成的 01 串,因此 fk(l,r) 的值不是 0 就是 1,而只有当 fk(l,r)=1 时才有意义。为此我们应该统计所有 fk(l,r)=1 的连续子串的长度总和。我们按右端点来对所有连续子串进行分类,当其右端点 r 固定后,我们要找到所有满足 fk(l,r)=1l,其中 l[1,r]。为了方便这里定义前缀异或和 si=a1,ka2,kai,k,因此就等价于找到所有满足 srsl=1,l[0,r1]l,然后再累加这些 lr 的长度,也就是子串的长度。为此可以开个两个哈希表 c0/1g0/1,分别维护 [0,r1]si=0/1 的下标数量,以及对应的下标的和。因此当 r 固定后,满足 fk(l,r)=1 的子串长度总和就是 rcsr1gsr1,对总的答案的贡献就是 2k(rcsr1gsr1)

   AC 代码如下,时间复杂度为 O(nlogA)

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 3e5 + 10, mod = 998244353;

int a[N];

int main() {
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", a + i);
    }
    int ret = 0;
    for (int k = 0; k <= 29; k++) {
        int sum = 0, c[2] = {0}, s[2] = {0};
        for (int i = 1; i <= n; i++) {
            c[sum]++, s[sum] = (s[sum] + i - 1) % mod;
            int x = a[i] >> k & 1;
            sum ^= x;
            ret = (ret + (1ll * c[sum ^ 1] * i % mod - s[sum ^ 1] + mod) % mod * (1 << k)) % mod;
        }
    }
    printf("%d\n", ret);

    return 0;
}

 

参考资料

  Educational Codeforces Round 155 — Editorial:https://codeforces.com/blog/entry/120773

posted @   onlyblues  阅读(71)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
历史上的今天:
2022-10-09 Using a Robot to Print the Lexicographically Smallest String
2022-10-09 最小移动距离
Web Analytics
点击右上角即可分享
微信分享提示