2023牛客暑期多校训练营5-I The Yakumo Family

2023牛客暑期多校训练营5-I The Yakumo Family

https://ac.nowcoder.com/acm/contest/57359/I

题意

在这里插入图片描述

解题思路

考虑将序列拆位计算。

先考虑一个简化版本,求:
∑ 1 ≤ l 1 ≤ r 1 ≤ n X O R ( l 1 , r 1 ) \sum_{1\le l_1\le r_1\le n}XOR(l_1,r_1) 1l1r1nXOR(l1,r1)

先对序列 a a a取前缀异或 b b b,一个区间 X O R ( l , r ) XOR(l_,r) XOR(l,r),其某一位是否有贡献取决于 b l − 1 ⊕ b r b_{l-1}\oplus b_r bl1br在这一位上是否为 1 1 1,若是,则这一位的贡献加一。对于每一位,我们可以根据 r 1 r_1 r1的后移,实时统计 1 / 0 1/0 1/0的个数 P 1 / P 0 P_1/P_0 P1/P0,对于每一个 r r r O ( 1 ) O(1) O(1)计算这一位 ∑ 1 ≤ l 1 ≤ r 1 X O R ( l 1 , r 1 ) = P b r ⨁ 1 \sum _{1\le l_1\le r_1}XOR(l_1,r_1)=P_{b_r\bigoplus 1} 1l1r1XOR(l1,r1)=Pbr1,设为 p r 1 p_{r_1} pr1。最后求取前缀和 s s s,得 s n s_n sn即为答案。

对于如下问题:
∑ 1 ≤ l 1 ≤ r 1 ≤ n ∑ r 1 < l 2 ≤ r 2 ≤ n X O R ( l 1 , r 1 ) × X O R ( l 2 , r 2 ) \sum_{1\le l_1\le r_1\le n}\sum_{r_1<l_2\le r_2\le n}XOR(l_1,r_1)\times XOR(l_2,r_2) 1l1r1nr1<l2r2nXOR(l1,r1)×XOR(l2,r2)
对于一个区间 X O R ( l 2 , r 2 ) XOR(l_2,r_2) XOR(l2,r2)的贡献同样可由上述方法求得,不同的是其对每一位的贡献为之前求得的 s l 2 − 1 s_{l_{2}-1} sl21,即 r 1 r_1 r1 [ 1 , l 2 − 1 ] [1,l_2-1] [1,l21]区间的总贡献。再求取一遍前缀和,可得答案。

k k k个不相交的区间,只需重复求取 k k k次,即可得答案。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+5,mod=998244353;
ll n,f[N],s[N],a[N];
ll t[N];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)cin>>f[i],t[i]=1,s[i]=s[i-1]^f[i];
	t[0]=1;
	for(int w=1;w<=3;w++){
		for(int j=0;j<=30;++j){
			ll p[2];
			p[0]=t[0],p[1]=0;
			for(int i=1;i<=n;++i){
				int g=(s[i]>>j)&1;
				a[i]=(a[i]+(p[g^1]<<j)%mod)%mod;
				p[g]+=t[i];
				p[g]%=mod;	
			}
		}
		t[0]=0;
		for(int i=1;i<=n;i++)t[i]=(t[i-1]+a[i])%mod,a[i]=0;
	}
	cout<<t[n];
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值