zoukankan      html  css  js  c++  java
  • xor问题的小结(HDU_5269 && HDU_5270 && NEU_1600)

    xor就是一个位运算的问题,做题的时候按二进制拆开,然后一位一位搞就好了,HDU_5269就是把数拆成二进制,然后维护一颗字母树,查找公共前缀的问题,(中间有几个小trick,秦总是dfs过的,然而我并没有去认真想怎么搞)。HDU_5270这题也是拆成2^i来搞的,但是题解上面说是归并搞(并没有看懂),如果按位直接从低位到高位来搞的话,不就是一个基数排序嘛,然后就是nlog(A)+nlogn的复杂度。NEU这道题是四省赛的题目,感觉可能就是HDU_5269的难度,BC第二题吧,就是把数拆开来,[l,r]这之间的数的第i位有多少个1。然后附上代码

    HDU_5269:

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    #define ll  long long
    #define FOR(i,x,y)  for(int i = x;i < y;i ++)
    #define IFOR(i,x,y) for(int i = x;i > y;i --)
    #define MOD 998244353
    
    using namespace std;
    
    const int MAXN = 50005;
    int ch[MAXN*32][2];
    int val[MAXN*32],sz;
    int num[32],cnt[32],n,m[MAXN];
    
    void init(){
        sz = 1;
        ch[0][1] = ch[0][0] = 0;
    }
    
    void translate(int s){
        FOR(i,0,32){
            num[i] = s%2;
            s /= 2;
        }
    }
    
    void insert(int* num,int v){
        int u = 0;
        FOR(i,0,32){
            int c = num[i];
            if(!ch[u][c]){
                ch[sz][0] = ch[sz][1] = 0;
                val[sz] = v;
                ch[u][c] = sz++;
            }
            else{
                val[ch[u][c]] += v;
            }
            u = ch[u][c];
        }
    }
    
    void find(int* num){
        int u = 0;
        FOR(i,0,32){
            int c = num[i];
            cnt[i] = val[ch[u][c]];
            u = ch[u][c];
        }
    }
    
    int main(){
        //freopen("test.in","r",stdin);
        int t,tCase = 0;
        scanf("%d",&t);
        while(t--){
            init();
            scanf("%d",&n);
            FOR(i,0,n){
                scanf("%d",&m[i]);
                translate(m[i]);
                insert(num,1);
            }
            ll ans = 0;
            FOR(i,0,n){
                translate(m[i]);
                find(num);
                IFOR(i,30,-1){
                    ll tem = cnt[i] - cnt[i+1];
                    if(!tem)    continue;
                    tem = (tem*(1<<(i+1))) % MOD;
                    ans += tem;
                    ans %= MOD;
                }
                ll tem = n - cnt[0];
                ans += tem;
                ans %= MOD;
            }
            printf("Case #%d: %I64d
    ",++tCase,ans);
        }
        return 0;
    }

    HDU_5270:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    #include <vector>
    #define ll  long long
    #define FOR(i,x,y)  for(int i = x;i < y;i ++)
    #define IFOR(i,x,y) for(int i = x;i > y;i --)
    
    using namespace std;
    
    const int N = 100005;
    ll a[N],b[N],x[N],y[N],px[N],py[N],p0[N],p1[N],z0[N],z1[N];
    int n;
    
    int Scan()
    {
        int res = 0, ch, flag = 0;
        if((ch = getchar()) == '-')
            flag = 1;
        else if(ch >= '0' && ch <= '9')
            res = ch - '0';
        while((ch = getchar()) >= '0' && ch <= '9' )
            res = res * 10 + ch - '0';
        return flag ? -res : res;
    }
    
    ll ll_Scan()
    {
        ll res = 0, ch, flag = 0;
        if((ch = getchar()) == '-')
            flag = 1;
        else if(ch >= '0' && ch <= '9')
            res = ch - '0';
        while((ch = getchar()) >= '0' && ch <= '9' )
            res = res * 10 + ch - '0';
        return flag ? -res : res;
    }
    
    void new_sort(ll* c,ll* p,ll* z,ll lowbit){
        ll MOD = lowbit << 1;
        int cnt0 = 0,cnt1 = 0;
        FOR(i,0,n){
            if(c[p[i]]&lowbit){
                z1[cnt1] = c[p[i]] % MOD;
                p1[cnt1++] = p[i];
            }
            else{
                z0[cnt0] = c[p[i]] % MOD;
                p0[cnt0++] = p[i];
            }
        }
        FOR(i,0,cnt0){
            p[i] = p0[i];
            z[i] = z0[i];
        }
        FOR(i,0,cnt1){
            p[i+cnt0] = p1[i];
            z[i+cnt0] = z1[i];
        }
    }
    
    ll find_ans(ll lowbit){
        int j1 = 0,j2 = 0,j3 = 0;
        while(j1 < n && x[0] + y[j1] < lowbit){
            j1 ++;
        }
        while(j2 < n && x[0] + y[j2] < (lowbit*2)){
            j2++;
        }
        while(j3 < n && x[0] + y[j3] < (lowbit*3)){
            j3++;
        }
        int c = (n + j2 - j1 - j3) % 2;
        FOR(i,1,n){
            while(j1 >= 1 && x[i] + y[j1-1] >= lowbit){
                j1--;
            }
            while(j2 >= 1 && x[i] + y[j2-1] >= lowbit*2){
                j2--;
            }
            while(j3 >= 1 && x[i] + y[j3-1] >= lowbit*3){
                j3--;
            }
            c = c ^ ((n + j2 - j1 - j3) % 2);
        }
        if(c)   return lowbit;
        else    return 0;
    }
    
    void solve(){
        ll ans = 0;
        FOR(i,0,n){
            px[i] = py[i] = i;
        }
        FOR(i,0,62){
            ll lowbit = (ll)1 << i;
            new_sort(a,px,x,lowbit);
            new_sort(b,py,y,lowbit);
            ans += find_ans(lowbit);
        }
        printf("%I64d
    ",ans);
    }
    
    int main()
    {
        //freopen("test.in","r",stdin);
        int t,tCase = 0;
        t = Scan();
        while(t--){
            printf("Case #%d: ",++tCase);
            n = Scan();
            FOR(i,0,n){
                a[i] = ll_Scan();
            }
            FOR(i,0,n){
                b[i] = ll_Scan();
            }
            solve();
        }
        return 0;
    }

    NEU_1600:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #define ll  long long
    #define FOR(i,x,y)  for(int i = x;i < y;i ++)
    #define IFOR(i,x,y) for(int i = x;i > y;i --)
    #define MOD 1000007
     
    using namespace std;
     
    const int M = 100005;
    const int N = 100005;
     
    int cnt[N][35],n,m,sum[N];
     
    int main()
    {
        //freopen("test.in","r",stdin);
        int t,tCase = 0;
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&m);
            printf("Case $%d:
    ",++tCase);
            FOR(i,0,n+1){
                FOR(j,0,16){
                    cnt[i][j] = 0;
                }
            }
            int res = (1<<16),num;
            int b_ans = 0;
            FOR(i,1,n+1){
                scanf("%d",&num);
                if(num >= res){
                    int tem = num >> 16;
                    tem = tem << 16;
                    b_ans += tem;
                    b_ans %= MOD;
                    num = num - tem;
                }
                FOR(sz,0,16){
                    int c = num % 2;
                    if(c)   cnt[i][sz] = cnt[i-1][sz] + 1;
                    else cnt[i][sz] = cnt[i-1][sz];
                    num >>= 1;
                }
            }
            while(m--){
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                int ans = b_ans;
                FOR(i,0,16){
                    int c = z % 2;
                    int tem = 1<<i;
                    if(!c)   ans += tem * (cnt[y][i] - cnt[x-1][i]);
                    else    ans += tem * ((y-x+1) - (cnt[y][i] - cnt[x-1][i]));
                    z >>= 1;
                    ans %= MOD;
                }
                printf("%d
    ",ans);
            }
        }
        return 0;
    }


    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    一题多解(六)—— 一个数二进制形式 1 的个数
    心算技巧
    心算技巧
    位运算应用及其注意事项
    位运算应用及其注意事项
    辨异 —— 不同的编程语言(编译型语言、解释型语言、动态语言、静态语言)
    C#POP3协议实现SSL验证登陆GMAIL
    PB学习笔记(一)
    24点计算 --- 庞果
    JAVA网站高并发解决方案
  • 原文地址:https://www.cnblogs.com/hqwhqwhq/p/4811902.html
Copyright © 2011-2022 走看看