zoukankan      html  css  js  c++  java
  • Codeforces Round #626 (Div. 2) D. Present(位运算)

    题意:

    求n个数中两两和的异或。

    思路:

    逐位考虑,第k位只需考虑0~k-1位,可通过&(2k+1-1)得到一组新数。

    将新数排序,当两数和在[2k,2k+1)和[2k+1+2k,2k+2)之间时该位为1,又因为两数的最大和为2*(2k+1-1)=2k+2-2,

    即当两数和在[2k,2k+1)和[2k+1+2k,2k+2-2]之间时该位为1。

    对于每个数,找到和

        大于等于2k

        小于2k+1

        大于等于2k+1+2k

    的三个临界点(因为两数之和一定小于等于2k+2-2,所以第四个临界点可以忽略),

    位于它们间的数与该数的和在第k位即为1,统计1的个数,该位异或偶数次后为0,异或奇数次后为1。

    Tips:

    调试了半天发现少加了一对括号,以后还是不要猜优先级了。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int MAX_N=1e6;
    
    int n,ans;
    int a[MAX_N],b[MAX_N];
    
    int main()
    {
        cin>>n;
        for(int i=0;i<n;i++) cin>>a[i];
    
        for(int k=0;k<25;k++){
            for(int i=0;i<n;i++)
                b[i]=a[i]&((1<<(k+1))-1);
            sort(b,b+n);
    
            int d=1<<k;
            int cnt=0;
    
            for(int i=n-1,x=0,y=0,z=0;i>=0;i--){
                while(x<n&&b[x]+b[i]<d) x++;
                while(y<n&&b[y]+b[i]<2*d) y++;
                while(z<n&&b[z]+b[i]<3*d) z++;
    
                cnt+=max(0,min(i,y)-x);
                cnt+=max(0,i-z);
            }
    
            if(cnt&1)
                ans|=1<<k;
        }
    
        cout<<ans<<endl;
    
        return 0;
    }
  • 相关阅读:
    第一阶段冲刺第三天
    第一阶段冲刺第二天
    第一阶段冲刺第一天
    典型用户和场景
    第十周学习进度条
    第九周学习进度条
    会议视频
    课堂练习……找水王
    小组项目需求——NABCD
    第二阶段个人总结三
  • 原文地址:https://www.cnblogs.com/Kanoon/p/12464094.html
Copyright © 2011-2022 走看看