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;
}

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