NC14414 小AA的数列

题解:求一个序列问长度为偶数且在[L, R]范围内的异或和的和,这个题考察的异或和的问题,因为异或和的话就要牵扯到二进制,所以一般来说这类问题就是将其拆开来进行计算。
首先:异或计算

1xor1=0,0xor0=0,1xor0=1

很容易可以得到一个结论,就是在某位上的时候,只有1才会影响到他的值,当1的个数为奇数时,二进制那个位置上才会计算出1这个数字。因为此题是处理一个区间的问题,为了减少时间复杂度,我们可以用到前缀和这个工具就是这样子

    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        a[i]=a[i]^a[i-1];
    }

这个题又有一个条件:保证区间为偶数,所以

    if(l&1) l++;
    if(r&1) r--;

接下来枚举二进制的1-32位每个位置的情况,计算出最终结果每一位上有多少个1是在符合条件的亦或过程中产生的,然后加权求和就可以。因为这个题目需要的区间是偶数长度的区间,因此如果j是奇数,则以j为右边界的满足条件的区间的左边界肯定都是奇数。如果j是偶数,则以j为右边界的满足条件的区间的左边界肯定都是偶数。因此为了计算满足以第j个数字为结尾的符合条件的区间其第i位的贡献,所以我们需要分奇数和偶数。

代码:

#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
const int maxn = 1e5+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 1e9+7;
using namespace std;
int a[maxn];
int dp[10][10];
int main()
{
    int n,l,r;
    cin>>n>>l>>r;
    if(l==r){
        cout<<0<<endl;
        return 0;
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        a[i]=a[i]^a[i-1];
    }
    if(l&1) l++;
    if(r&1) r--;
    ll ans=0;
    for(int i=0;i<32;i++){
        memset(dp,0,sizeof(dp));
        ll sum=0,temp=1<<i;
        for(int j=l;j<=n;j++){
            dp[(a[j-l]>>i)&1][(j-l)&1]++;
            sum+=dp[((a[j]>>i)&1)^1][j&1];
            if(j>=r) dp[(a[j-r]>>i)&1][(j-r)&1]--;
        }
        ans=(ans+temp*sum%mod)%mod;
    }
    cout<<ans<<endl;
    return  0;

}
题解 文章被收录于专栏

主要写一些题目的题解

全部评论

相关推荐

12-06 16:17
济宁学院 Java
点赞 评论 收藏
分享
想干测开的tomca...:这份简历是“大一新生硬凹资深后端”的典型反面教材,槽点离谱到能让面试官直接笑出声: ### 1. 「年龄+入学时间」和项目复杂度完全脱节,可信度直接归0 你2024年7月才入学(现在刚读了1年多),19岁的大一新生,能把Vue3+Spring Boot+ShardingSphere+K8s+AI这些技术全塞进两个项目里?别说实际开发,光把这些技术的文档看完都得半年——这不是“能力强”,是“把招聘JD里的技术词全抄过来造假”,明摆着没碰过实际代码
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务