1. 程式人生 > >2017.10.12 小Q的無敵異或 失敗總結

2017.10.12 小Q的無敵異或 失敗總結

第一問是可以O(n)的

二進位制位是獨立的,所以直接分開算即可。。

記一個字首和,開桶裝0、1的個數     然後每次新加入一個點就直接更新就可以了

第二問就比較難了,,手玩只能發現最低位可以這麼搞,對於高位還要考慮借位情況,借位情況有0有1,就不好離散

但是這麼做是可以做出來的。。只是要在模意義下進行,,再考慮每次-的過程,都是一個字首和-比他靠前的字首和,

當差值>列舉次數時,顯然影響是1  

差值要考慮進位的情況,,這樣似乎就形成了一個偏序關係,,就可以用樹狀陣列了。。

碼(借鑑):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define P 998244353
ll ans,n,j,i,k,lin,er[50],he[50][100005],lie[100005],dui[100005],v[100005],a[100005],tong[100006],p[100005];
 
int lowbit(int a)
{
    return a&(-a);
}
 
void jia(int o,int z)
{
    for(;o<=dui[0];o+=lowbit(o))
    {
        v[o]^=z;
    }   
}
int cha(int o)
{
    int ans=0;
    for(;o;o-=lowbit(o))
    {
        ans^=v[o];
    }return ans;
}
int find(ll o)
{
    if(o<0)return 0;
    int l=1,r=dui[0]+1;
    while(l+1<r)
    {
    int mid=(l+r)>>1;
    if(dui[mid]<=o)l=mid;
    else r=mid; 
    }   
    return l;
}
 
 
 
int main()
{   
    er[0]=1;
    for(i=1;i<=40;i++)
    er[i]=er[i-1]*2;
    scanf("%lld",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);        
    }
    for(i=0;i<=20;i++)
    for(j=1;j<=n;j++)
    {
    he[i][j]=he[i][j-1]^(a[j]&er[i]);
    if(he[i][j]&er[i])tong[i]++;
    }
    for(i=0;i<=20;i++)
    {
        for(j=1;j<=n;j++)
        {
    ans=1ll*(ans+1ll*tong[i]*er[i])%P;
    if(a[j]&er[i])
    {
        tong[i]=(n-j)-(tong[i]-1);
    }       
        }       
    }
    printf("%lld ",ans);
    ans=0;
      for(i=1;i<=n;i++)he[0][i]=he[0][i-1]+a[i];  
    for(k=0;k<=37;k++){  
        for (i=0; i<=n; i++) tong[i]=p[i]=he[0][i]&(er[k+1]-1);  
        dui[0]=0;
        sort(tong,tong+n+1); dui[++dui[0]]=tong[0];  
        memset(v,0,sizeof(v));  
        for (i=1; i<=n; i++)  
            if (tong[i]!=tong[i-1]) dui[++dui[0]]=tong[i];  
        int lin=0;  
        for (i=0; i<=n; i++){  
            lin^=cha(find(p[i]-er[k]))^cha(find(p[i]))^cha(find(p[i]+er[k]));  
            //cout<<er[k]<<" "<<lin<<" ";
            jia(find(p[i]),1);    
        } //cout<<lin<<endl; 
        if (lin) ans|=er[k];  
         
    }  
    printf("%lld",ans);
}