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\n",++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\n",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:\n",++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\n",ans);
        }
    }
    return 0;
}


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

转载于:https://www.cnblogs.com/hqwhqwhq/p/4811902.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值