• bzoj 4017: 小Q的无敌异或


    4017: 小Q的无敌异或

    Time Limit: 20 Sec  Memory Limit: 128 MB
    Submit: 736  Solved: 242
    [Submit][Status][Discuss]

    Description

    背景
     
    小Q学习位运算时发现了异或的秘密。
     
    描述
     
    小Q是一个热爱学习的人,他经常去维基百科(http://en.wikipedia.org/wiki/Main_Page)学习计算机科学。
     
    就在刚才,小Q认真地学习了一系列位运算符(http://en.wikipedia.org/wiki/Bitwise_operation),其中按位异或的运算符 xor 对他影响很大。按位异或的运算符是双目运算符。按位异或具有交换律,即i xor j = j xor i。
     
    他发现,按位异或可以理解成被运算的数字的二进制位对应位如果相同,则结果的该位置为0,否则为1,例如1(01) xor 2(10) = 3(11)。
     
    他还发现,按位异或可以理解成数字的每个二进制位进行了不进位的加法,例如3(11) xor 3(11) = 0(00)。
     
    于是他想到了两个关于异或的问题,这两个问题基于一个给定的非负整数序列A1, A2, ..., An,其中n是该序列的长度。
     
    第一个问题是,如果用f(i, j)表示Ai xor Ai+1 xor ... xor Aj,则任意的1 <= i <= j <= n的f(i, j)相加是多少。
     
    第二个问题是,如果用g(i, j)表示Ai + Ai+1 + ... + Aj,则任意的1 <= i <= j <= n的g(i, j)异或在一起是多少。
     
    比如说,对于序列{1, 2},所有的f是{1, 2, 1 xor 2},加起来是6;所有的g是{1, 2, 1 + 2},异或起来是0。
     
    他觉得这两个问题都非常的有趣,所以他找到了你,希望你能快速解决这两个问题,其中第一个问题的答案可能很大,你只需要输出它对998244353(一个质数)取模的值即可。
     

     

    Input

    第一行一个正整数n,表示序列的长度。
     
    第二行n个非负整数A1, A2, ..., An,表示这个序列。
     

    Output

    两个整数,表示两个问题的答案,空格隔开,其中第一个问题的答案要对998244353(一个质数)取模。
     

    Sample Input

    2
    1 2

    Sample Output

    6 0

    HINT

    100%的数据满足n <= 10^5, Ai <= 10^6。
        很棒的一道题啊hhhhhh。
        很显然第一问是easy模式,直接处理出前缀Xor数组直接拆位算贡献好啦(因为太简单就不仔细说这一部分了hhhh)。
         
        第二问嘛,,,稍微有那么点麻烦hhhhh
        考虑到前缀和可能是 10^11 级别的,所以我们的二进制要考虑前30多位,并且将会涉及一系列long long的问题(哪一步不小心可能就炸int了hhhh,但为了卡一卡常我尽量都用int.....)。
        因为答案是所有区间和异或起来,所以我们就依次考虑 2^i 在答案里是1还是0就好了,然后请转到 : https://www.lydsy.com/JudgeOnline/problem.php?id=4888 ,我是延用了我早期解这个题用的套路 (只不过太早期了在我的博客里找不着hhhh),就是考虑第i位的时候,把所有数分成 这一位是1 和 这一位是0 两种数,分别计算(这里就把推东西的环节留给你们 了hhhh),只不过这个题的前缀和太大了,我们还需要离散化一下。
        emmmm然后就做完了。
     
    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int ha=998244353,maxn=100005;
    int n,m,Xor[maxn],num[35][2],F[2][maxn],ky;
    inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x;}
    inline void update(int T,int x){ for(;x<=ky;x+=x&-x) F[T][x]^=1;}
    inline int query(int T,int x){ int an=0; for(;x;x-=x&-x) an^=F[T][x]; return an;}
    ll a[maxn],now,N[maxn],A[maxn],ci[66];
    
    inline int solve1(){
    	int ans=0;
    	for(int i=0;i<=20;i++) num[i][0]++;
    	for(int i=1;i<=n;i++){
    		Xor[i]=a[i]^Xor[i-1]; 
    		for(int j=0;j<=20;j++) ans=add(ans,ci[j]*(ll)((Xor[i]&ci[j])?num[j][0]:num[j][1])%ha);
    		for(int j=0;j<=20;j++) num[j][(Xor[i]&ci[j])?1:0]++;
    	}
    	return ans;
    }
    
    inline ll solve2(){
    	ll ans=0; int tmp=0;
    	for(int i=1;i<=n;i++) a[i]+=a[i-1];
    	
    	for(int i=0;i<=40;now|=ci[i],i++,tmp=0){
    		memset(F,0,sizeof(F));
    		
    		for(int j=1;j<=n;j++) A[j]=N[j]=a[j]&now;
    		sort(N+1,N+n+1);
    		ky=unique(N+1,N+n+1)-N-1;
    		for(int j=1;j<=n;j++) A[j]=lower_bound(N+1,N+ky+1,A[j])-N;
    		
    		for(int j=1,u;j<=n;j++){
    			u=(ci[i]&a[j])?1:0;
    			tmp^=query(u^1,A[j])^query(u,ky)^query(u,A[j])^u;
    			update(u,A[j]);
    		}
    		
    		if(tmp&1) ans+=ci[i];
    	}
    	return ans;
    }
    
    int main(){
    	ci[0]=1; for(int i=1;i<=40;i++) ci[i]=ci[i-1]+ci[i-1];
    	scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld",a+i);
    	printf("%d ",solve1()),printf("%lld
    ",solve2());
    	return 0;
    }
    

      

  • 相关阅读:
    BZOJ-1034: [ZJOI2008]泡泡堂BNB (田忌赛马贪心)
    BZOJ-2190: [SDOI2008]仪仗队 (欧拉函数)
    BZOJ-1864: [Zjoi2006]三色二叉树 (julao都说简单的树形DP)
    BZOJ-2657: [Zjoi2012]旅游(journey) (树形DP求最长链)
    BZOJ-2241: [SDOI2011]打地鼠 (模拟+枚举)
    BZOJ-1207: [HNOI2004]打鼹鼠 (LIS类似DP)
    BZOJ-1821: [JSOI2010]Group 部落划分 Group (二分+并查集)
    BZOJ-1218: [HNOI2003]激光炸弹 (前缀和+模拟)
    [SinGuLaRiTy] ZKW线段树
    [SinGuLaRiTy] 字节大小
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8964413.html
Copyright © 2020-2023  润新知