小AA的数列

小AA的数列

https://ac.nowcoder.com/acm/problem/14414

题意:给出一个长度为n的序列,要求区间长度在[L,R]之间且为偶数的区间异或和之和?

思路:参考:https://blog.nowcoder.net/n/4dacd8e372de4199a30442b4eee1849a
sum[i][j]为前i个数在第j位为1的个数
pre[i][j][0]为在sum[k][j] (k<=i&&k>=1&&k图片说明i mod(2) )中为偶数的个数
pre[i][j][1]为在sum[k][j] (k<=i&&k>=1&&k图片说明i mod(2) )中为奇数的个数
结果等于每一位在规定区间长度内为偶数的区间的数目为奇数的区间数乘以位权之和

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 1000000007

using namespace std;

int n, l, r, a[100005], sum[100005][31], pre[100005][31][2];
ll ans=0;

void solve()
{
    for(int i=1; i<=n; i++)
    {
        for(int j=0; j<31; j++)
        {
            sum[i][j]=sum[i-1][j]+((a[i]>>j)&1);
            if(i!=1)
            {
                pre[i][j][0]=pre[i-2][j][0];
                pre[i][j][1]=pre[i-2][j][1];
            }
            pre[i][j][sum[i][j]%2]++;
            //printf("%d ",pre[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*(pre[r1][j][1-sum[i-1][j]%2]-pre[l1-2][j][1-sum[i-1][j]%2])%inf)%inf;
            else
                ans=(ans+(1LL<<j)%inf*pre[r1][j][1-sum[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哈:Radis写错了兄弟
点赞 评论 收藏
分享
11-15 19:28
已编辑
蚌埠坦克学院 硬件开发
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务