NC14414 小AA的数列(二进制枚举)

题目链接

题意:
给定一个数列,找出这个数列中长度为偶数的连续子列的异或和
LR并且要求长度为偶数的同时满足在L到R之间
mod 1e9+7最后结果mod ~1e9+7
题解:
n,L,R<=1e5n2n,L,R<=1e5,所以不能考虑n^2暴力了
之前比较经典的就有选任意两位数异或的总和
那个题可以考虑枚举二进制位,然后看每一位的贡献有多少
1其实就是每一位有多少种异或后成1的方法
算出来之后乘这一二进制位的权重即可

这道题肯定也是类似,需要对每一二进制位进行分开考虑
然后一步一步分析差别

首先,这道题需要考虑的是一个连续子列
连续子列我们可以维护一个前缀和
sum[r] xor sum[l1]==1lr1如果sum[r] ~xor~ sum[l-1]==1说明l-r的贡献为1
xor00如果xor为0,说明这之间的异或也为0,没有贡献
那么枚举每个前缀的二进制位
看在某一个二进制位上这个前缀的前面有多少个与他相反的前缀
然后每一二进制位综合起来乘上权值就可以算出来最后的结果

然后,考虑一下偶数的限制
其实很简单,两个奇数或者两个偶数相减才是偶数
l1r542,3,4,5比如前缀下标l是1,r是5,相减是4个,中间有数2,3,4,5
l2r423,4l是2,r是4,相减2个,中间数是3,4
所以对把刚才那个维护个数的数组再加一维,这一维存奇偶数位置
这样就把偶数的限制解决了

L,R最后解决一下L,R的限制
这样其实数组不用改变
LR你只要保证,数组中的个数所对应的位置和当前这个位置是在L到R即可
L那么,其实就是对于每个位置,如果他到和当前位置如果距离刚好是L
R就把这个位置作为贡献加入,直到往后枚举如果他和枚举的位置距离成R的时候
LR再把他减去,就保证了这个位置和后面的位置形成的区间长度都在L到R之间

这样一步一步解决完了
只要写出来代码就行了
L,R还有一个比较直接的问题,题目没有限定L,R一定为偶数
L==R0如果区间里只有奇数,即L==R并且为奇数那么结果肯定是0
L,R还有如果L,R为奇数的时候,但不可能出现奇数,所以往中间减少一下

AC代码

/*
    Author:zzugzx
    Lang:C++
    Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};

ll c[2][2],a[maxn];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n,l,r;
    cin>>n>>l>>r;
    if(l==r&&l&1){cout<<0;return 0;}
    if(l&1)l++;if(r&1)r--;
    for(int i=1;i<=n;i++)cin>>a[i],a[i]^=a[i-1];
    ll ans=0;
    for(int i=0;i<=31;i++){
        memset(c,0,sizeof c);
        for(int j=1;j<=n;j++){
            if(j>=l)c[j&1][(a[j-l]>>i)&1]++;
            ans=(ans+c[j&1][(a[j]>>i)&1^1]*(1ll<<i)%mod)%mod;
            if(j>=r)c[j&1][(a[j-r]>>i)&1]--;
        }
    }
    cout<<ans;
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章