小AA的数列

小AA的数列

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

题解:

很套路的一道题:由于所求的是异或之和,我们知道位运算不产生进位,所以每个数位与位之间的贡献是独立的,不想不影响,那么我们考虑按位计算对 答案的贡献即可,
令pre[i][j]表示 前i个数中第j位为1的个数,那么当我们枚举所有区间的左端点i时,如果pre[i-1][j]是奇数,那么所有能对答案造成贡献的右端点r的pre[r][j]一定是偶数,反之亦然。
所以,我们在令cnt[i][j]表示前i个数中,pre[i][j]为奇数的个数,但是题目还有一个限制条件就是长度必须是偶数,所以我们把cnt[i][j]表示前面与i奇偶性相同的个数,
这样,当我们枚举所有区间的左端点i时,就可以O1的计算答案了~


代码:

#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define fi first
#define se second
#define pb push_back
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
using namespace std;
typedef long long ll;
typedef vector<int> VI;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const  ll inf  = 0x3f3f3f3f3f3f3f3f;
const int mod  = 1e9+7;
const int maxn = 1e5 + 4;
const int N    = 5e3 + 5;
const double eps = 1e-6;
const double pi = acos(-1);
ll qpow(ll x,ll y){ll ans=1;x%=mod;while(y){ if(y&1) ans=ans*x%mod; x=x*x%mod; y>>=1;}return ans;}


int n,l,r,pre[maxn][31],cnt[maxn][31],a[maxn];
ll ans;
int main(){
    //freopen("input.in","r",stdin);
    scanf("%d%d%d",&n,&l,&r);
    for(int i=1;i<=n;i++) {
        scanf("%d",&a[i]);
        for(int j=0;j<=30;j++) {
            pre[i][j]=(a[i]>>j)&1;
        }
        for(int j=0;j<=30;j++) {
            pre[i][j]+=pre[i-1][j];
            cnt[i][j]=pre[i][j]&1;
        }
        for(int j=0;j<=30;j++) {
            if(i>1) cnt[i][j]+=cnt[i-2][j];
        }
    }
    for(int i=1;i+l-1<=n;i++) {
        int L=i+l-1,R=min(n,i+r-1);
        if((L-i+1)&1) L++;
        if((R-i+1)&1) R--;
        if(L>R) continue;

        for(int j=0;j<=30;j++) {
            ll k=cnt[R][j]-cnt[max(0,L-2)][j];
            if(pre[i-1][j]&1) ans+=1ll*((R-L+2)/2-k)*(1<<j)%mod;
            else ans+=k*(1<<j)%mod;
            //cout<<i<<','<<j<<','<<k<<endl;
            ans%=mod;
        }
        //cout<<ans<<endl;
    }
    printf("%lld\n",ans);
}






全部评论

相关推荐

贪食滴🐶:你说熟悉扣篮的底层原理,有过隔扣职业球员的实战经验吗
点赞 评论 收藏
分享
11-14 16:13
已编辑
重庆科技大学 测试工程师
Amazarashi66:不进帖子我都知道🐮❤️网什么含金量
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务