【DP+位运算+思维+异或子集合】 UVALive - 8518 G - Sum of xor sum

G - Sum of xor sum UVALive - 8518

感谢男朋友的悉心教导!!!

给你n个数,进行Q次询问,每次询问都问你l-r区间内所有数的子集合的异或值之和%1e9+7
首先s[]:存储前缀异或和:s[i]=s[i-1]^a[i],那么a[l]+a[l+1]+……+a[r]=s[r]-s[l-1];
接下来预处理k[i][j][k],存储前i个前缀异或值,二进制位为j是k的个数
t[i]:存储1-i中所有子集合的异或值之和
t[i]=t[i-1]+s[0]^s[i]+s[1]^s[i]+……+s[i-1]^s[i]
那么s[0]^s[i]+s[1]^s[i]+……+s[i-1]^s[i]可以通过前i个数第j位的值与我当前前缀异或值不同的话,那么每个k[i][j][k]可以贡献的值是1<<j;
所以进行询问时,ans=t[r]-t[l-1]-sum
sum是左端点在0-(l-2),右端点在l-r中的所有异或和
所以就应该用sum+=左边所有数j位为1*右边所有数j位为0+左边所有数j位为0*右边所有数j位为1*(1<<j)--->当前位的贡献值

 



#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int mod=1e9+7;
int s[maxn],k[maxn][23][2],t[maxn];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,Q;
        scanf("%d%d",&n,&Q);
        for(int i=0;i<=21;i++)
            k[0][i][0]=1;
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            s[i]=s[i-1]^x;
            for(int j=21;j>=0;j--)
            {
                if((s[i]>>j)&1)
                {
                    k[i][j][1]=k[i-1][j][1]+1;
                    k[i][j][0]=k[i-1][j][0];
                }
                else
                {
                    k[i][j][0]=k[i-1][j][0]+1;
                    k[i][j][1]=k[i-1][j][1];
                }
            }
            t[i]=t[i-1];
            for(int j=21;j>=0;j--)
            {
                if((s[i]>>j)&1) t[i]=(t[i]+((1<<j)*k[i][j][0]%mod))%mod;
                else t[i]=(t[i]+((1<<j)*k[i][j][1])%mod)%mod;
            }
        }
        while(Q--)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            int ans=(t[r]-t[l-1]+mod)%mod;
            if(l>=2)
            {
                for(int j=21; j>=0; j--)
                {
                    int x1=k[r][j][1]-k[l-1][j][1],x2=k[r][j][0]-k[l-1][j][0];
                    int y1=k[l-2][j][1],y2=k[l-2][j][0];
                    ans=(mod+ans-((1<<j)*(x1*y2+x2*y1)%mod))%mod;
                }
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

 

猜你喜欢

转载自blog.csdn.net/qq_41037114/article/details/82891940
sum