题解:小AA的数列

小AA的数列

http://www.nowcoder.com/questionTerminal/abdcf8411f1343ecb1d5479f664d61b1

又是求异或和的和的常见套路——按位计算,即计算二进制中每一位的贡献。

需要注意的是,题目要求的不仅要区间长度在[L,R],而且区间长度必须是偶数(因为这个debug了好久qwq)

我们先来简化下题目。

我们假设只考虑一个二进制位x,并且区间长度也可以为奇数,那么这个怎么做呢?

很简单,我们为了方便处理,先做个前缀和,sum[i]sum[i]表示,前i个数字中,二进制第x位为1的数字的个数。

然后,我们就来统计答案,为了好计算,我们肯定要先固定区间的一个端点,于是,我们先枚举左端点l,那么,明显的,对答案有贡献的只有第x位为1的个数是奇数的区间,每个这样的区间都会产生贡献2^{x-1}2
x−1
的贡献,那么,我们统计有几个这样的区间就行了。

注意到,因为左端点固定,所以一个区间中,第x位为1的数字的个数即是sum[i]-sum[l-1]sum[i]−suml−1

因为l是确定的,所以sum[l-1]sum[l−1]的奇偶性也是确定的,那么,我们只需要统计所有满足条件的右端点i中,sum[i]sum[i]的奇偶性和sum[l-1]sum[l−1]相反的个数即可。

那么,我们开个辅助数组cnt[i][0/1]cnt[i][0/1]表示前i个数字中,sum[i]sum[i]为偶/奇的个数,那么,只要我们预处理好sum[i]sum[i]和cnt[i]cnt[i]这两个数组,我们就可以直接O(1)O(1)计算出左端点确定时,对答案有贡献的右端点的数量,这个数量再乘单个的贡献,即为只考虑一个x位时的答案。

这样,就完成了。

那么,现在来加强下,我们再令区间长度必须为偶数,这个怎么办呢?

还是同样的方法,我们确定了左端点,那么,对于一个区间长度的奇偶性合法的右端点i来说,i+2,i+4...也是合法的,于是,我们将原序列奇偶分割,即,我们统计cnt的时候(sum就不用了,sum必须保持值正确),只用i-2去更新i,这样,奇偶性合法的就在一起被统计到了(注意特判1)

然后,计算的时候,由于又要区间长度为[L,R],所以我们再修改下左右端点,使其从合法的位置开始即可~

然后,再把每个二进制位都计算出来,就是最终答案了
来源:https://blog.nowcoder.net/n/4dacd8e372de4199a30442b4eee1849a

代码如下:
#include<bits/stdc++.h>
#define LL long long
#define INF 1000000007
using namespace std;
int n, l, r, a[100005], ans[100005][31], sw[100005][31][2];
LL ans=0;

void solve()
{
for(int i=1; i<=n; i++)
{
for(int j=0; j<31; j++)
{
ans[i][j]=ans[i-1][j]+((a[i]>>j)&1);
if(i!=1)
{
sw[i][j][0]=sw[i-2][j][0];
sw[i][j][1]=sw[i-2][j][1];
}
sw[i][j][ans[i][j]%2]++;
//printf("%d ",sw[i][j][1]);
}
//printf("\n");
}
for(int i=1; i<=n-l+1; i++)
{
int l1=i+l-1, r1=min(i+r-1,n);
if(l%2==1)
{
l1++;
}
if((r1-i+1)%2==1)
{
r1--;
}
if(l1>r1)
{
continue;
}
for(int j=0; j<31; j++)
{
if(l1>1)
ans=(ans+(1LL<<j)%INF(sw[r1][j][1-ans[i-1][j]%2]-sw[l1-2][j][1-ans[i-1][j]%2])%INF)%INF;
else
ans=(ans+(1LL<<j)%INF
sw[r1][j][1-ans[i-1][j]%2]%INF)%INF;
}
}
}

int main()
{
scanf("%d%d%d",&n,&l,&r);
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
}
solve();
cout << ans << endl;
return 0;
}

全部评论

相关推荐

咦哟,从去年八月份开始长跑,两处实习转正都失败了,风雨飘摇,终于拿到offer了更新一下面试记录:秋招:多部门反复面试然后挂掉然后复活,具体问了啥已经忘了,只是被反复煎炸,直至焦香😋春招:base北京抖音hr打来电话说再次复活,准备面试,gogogo北京抖音一面:六道笔试题:1.promise顺序2.定义域问题3.flat展开4.并发请求5.岛屿数量算法(力扣)深度,广度都写6.忘记了,好像也是算法,难度中等其他问题多是框架底层设计,实习项目重难点~~~秒过😇北京抖音二面:三道笔试题:(为什么只有三道是因为第三道没做出来,卡住了)1.中等难度算法(忘记啥题了,应该是个数组的)2.认识js的继承本质(手写继承模式,深入js的面相对象开发)3.手写vue的响应式(卡在了watch,导致挂掉)---后知后觉是我的注册副作用函数写得有问题,有点紧张了其他题目多是项目拷打,项目亮点,对实习项目的贡献~~~第二天,挂,but立马复活转战深圳客服当天约面深圳客服一面:六道笔试题,由于面过太多次字节,面试官叫我直接写,不用讲,快些写完😋,具体都是些继承,深拷贝(注意对数组对象分开处理,深层次对象,循环引用),加中等难度算法题~~~秒过深圳客服二面:口诉八股大战:大概囊括网络,浏览器渲染原理,动画优化,时间循环,任务队列等等(你能想到的简单八股通通拉出来鞭尸😋)算法题:笔试题6道:1:找出数组内重复的数,arr[0]-arr[n]内的数大小为[1-n],例如[1,2,2,3,3]返回[2,3],要求o(n),且不使用任何额外空间(做到了o(n),空间方面欠佳,给面试官说进入下一题,做不来了)2:原滋原味的继承(所以继承真滴很重要)3:力扣股票购买时机难度中等其他滴也忘记了,因为拿到offer后鼠鼠一下子就落地了,脑子自动过滤掉可能会攻击鼠鼠的记忆😷~~~秒过深圳客服三面:项目大战参与战斗的人员有:成员1:表单封装及其底层原理,使用成本的优化,声明式表单成员2:公司内部库生命周期管理成员3:第三方库和内部库冲突如何源码断点调试并打补丁解决成员4:埋点的艺术成员5:线上项目捷报频传如何查出内鬼成员6:大文件分片的风流趣事成员7:设计模式对对碰成员8:我构建hooks应对经理的新增的小需求的故事可能项目回答的比较流利,笔试题3道,都很简单,相信大家应该都可以手拿把掐😇~~~过过过无hr面后续煎熬等待几天直接hr打电话发offer了,希望大家也可以拿到自己心仪的offer
法力无边年:牛哇,你真是准备得充分,我对你没有嫉妒,都是实打实付出
查看19道真题和解析
点赞 评论 收藏
分享
牛客583549203号:腾讯还好,况且实习而已,实习生流动性很大,属于正常现象,记得和HR委婉解释
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务