zoukankan      html  css  js  c++  java
  • 关于xor

    有关异或的一些习题整理


    第一个:

    给出一个序列

    求子集的算术和的异或和

    爆搜是不行的,但是STL库很好

    bitset

    #include <cstdio>
    #include <iostream>
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    using namespace std;
    
    #define MAXN 2000001
    bitset <MAXN> a;
    int n,x,h,ans;
    int main() {
        cin>>n;
        a[0]=1;
        for (int i=1;i<=n;i++) {
            cin>>x;
            a^=(a<<x);
            h+=x;
        }
        for (int i=h;i;i--) {
            if (a[i]) {
                ans^=i;
            }
        }
        cout<<ans<<endl;
        return 0;
    }

    然后呢?


    下面一个:

    奶牛异或:

    在一个序列中,找一段连续子序列异或和最大:

    #include <cstdio>
    #include <iostream>
    #include <string>
    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    
    const int MAXN = 50005;
    const int maxnode = MAXN * 33;
    const int sigma_size = 2;
    const int INF = (1LL << 31) - 1;
    
    struct Trie {
        int ch[maxnode][sigma_size];
        int val[maxnode];
        int sz;
        void clear() {
            sz = 1;
            memset(ch[0], 0, sizeof(ch[0]));
        }
        Trie() {
            clear();
        }
    
        int idx(char c) {
            return c - '0';
        }
        void insert(char *s, int v) {
            int u = 0, n = strlen(s);
            for(int i = 0; i < n; i++) {
                int c = idx(s[i]);
                if(!ch[u][c]) {
                    memset(ch[sz], 0, sizeof(ch[sz]));
                    val[u] = 0;
                    ch[u][c] = sz++;
                }
                u = ch[u][c];
            }
            val[u] = v;
        }
    
        //^0 equal
        //^1 opposite
        int find(char *s, int value, int dir) {
            int u = 0, n = strlen(s);
            for(int i = 0; i < n; i++) {
                int c = idx(s[i]);
                int v = c ^ dir;
                if(!ch[u][v])
                    v ^= 1;
                u = ch[u][v];
            }
            return val[u] ^ value;
        }
    
    } trie;
    
    int n, sum[MAXN], A[MAXN];
    char bit[33];
    
    void trans(char *s, int v) {
        for(int i = 31; i >= 0; i--)
            s[i] = ((v >> i) & 1) + '0';
        s[32] = '';
        reverse(s, s+32);
    }
    
    int f[101][101];
    
    int main() {
        scanf("%d", &n);
        sum[0] = 0;
        for(int i = 1; i <= n; i++) {
            scanf("%d", &A[i]);
            sum[i] = sum[i-1] ^ A[i];
        }
        trans(bit, 0);
        trie.insert(bit, 0);
        int maxv = -INF, minv = INF;
        int mx, mi;
        for(int i = 1; i <= n; i++) {
            trans(bit, sum[i]);
            mi = trie.find(bit, sum[i], 0);
            mx = trie.find(bit, sum[i], 1);
            minv = min(mi, minv);
            maxv = max(mx, maxv);
            trie.insert(bit, sum[i]);
        }
    
        //printf("%d %d
    ", maxv, minv);
        cout<<maxv<<" ";
        for (int i=1;i<=n;i++) {
            f[i][i]=A[i];
        }
        for (int l=2;l<=n;l++) {
            for (int i=1;i+l-1<=n;i++) {
                int j=i+l-1;
                f[i][j]=f[i][j-1]^A[j];
            }
        }
        for (int i=1;i<=n;i++) {
            for (int j=i+1;j<=n;j++) {
                if (f[i][j]==maxv) {
                    cout<<i<<" "<<j<<endl;
                    return 0;
                }
            }
        }
        return 0;
    }

    然后呢?


    下面一个:

    求一个序列所有连续和的异或值

    #include <cstdio>
    #include <iostream>
    #include <string>
    #include <bits/stdc++.h>
    
    using namespace std;
    #define MAXN 1000001
    int c[MAXN][2];
    int s[MAXN],a[MAXN],ans;
    int pw[21],n;
    
    void add(int x,int y) {
        while (x<=1000000) {
            c[x][y]++;
            x+=(x&(-x));
        }
    }
    int query(int x,int y) {
        int sum=0;
        while (x) {
            sum+=c[x][y];
            x-=(x&(-x));
        }
        return sum;
    }
    int main() {
        int flag,cnt;
        cin>>n;
        for (int i=1; i<=n; i++) {
            scanf("%d",&s[i]);
            s[i]+=s[i-1];
        }
        pw[0]=1;
        for (int i=1; i<=20; i++)
            pw[i]=pw[i-1]*2;
        for (int i=0; i<=20; i++) {
            if (pw[i]<=s[n]) {
                memset(c,0,sizeof(c));
                flag=0;
                add(1,0);
                for (int j=1; j<=n; j++) {
                    int tmp=s[j]&pw[i];
                    if (tmp) {
                        cnt=query(a[j]+1,0)+query(1000001,1)-query(a[j]+1,1);
                    } 
                    else  {
                        cnt=query(a[j]+1,1)+query(1000001,0)-query(a[j]+1,0);
                    }
                    if (cnt%2==1) flag^=1;
                    add(a[j]+1,(bool)tmp);
                    if (tmp)  {
                        a[j]|=pw[i];
                    }
                }
                if (flag) {
                    ans|=(pw[i]);
                } 
            }
        }
        cout<<ans;
        return 0;
    }

    下面呢?


    再来一个:

     给定序列
    多次输入起点终点
    求起点连续异或到终点的值

    #include <cstdio>
    #include <iostream>
    #include <string>
    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    
    /*
    给定序列
    多次输入起点终点
    求起点连续异或到终点的值 
    */
    
    void init()
    {
        int n=0,sum=0;
        for(int i=1; i<=100; i++)
        {
            printf("%d %d
    ",n,sum);
            n^=i;
            sum^=n;
        }
    }
    long long xo(int x)///A0xorA1...xorAx
    {
        long long n=0,sum=0;
        if(x<=7)
            for(int i=1; i<=x; i++)
                {
                    n^=i;
                    sum^=n;
                }
        else
        {
            int m=x;
            m-=7;
            int pos=m%8;
            if(x<4)
                for(int i=1; i<=x; i++)
                    n^=i;
            m-=3;
            int pos1=n%4;
            for(int i=x-pos1+1; i<=x; i++)
                    n^=i;
            for(int i=x-pos+1; i<=x; i++)
                {
                    n^=i;
                    sum^=n;
                }
        }
        return sum;
    }
    int main()
    {
        int T,l,r;
        //init();
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d %d",&l,&r);
            printf("%lld
    ",xo(r)^xo(l-1));
        }
        return 0;
    }

    接下来 还有:


    下一个:

    给定序列
    求连续子区间异或值的和:

    #include <cstdio>
    #include <iostream>
    #include <string>
    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    
    /*
    给定序列
    求连续子区间异或值的和
    */
    
    const int maxn = 2e5+7;
    int sum[maxn],a[maxn],c[maxn];
    int main() {
        int n;
        scanf("%d",&n);
        sum[0] = 0;
        for(int i=1; i<=n; i++) {
            scanf("%d",&a[i]);
            sum[i] = sum[i]^a[i];
        }
        int ans = 0;
        for(int k=0; k<=29; k++) {
            c[0] =1 ,c[1] =0;
            for(int i=1; i<=n; i++) {
                int v = (sum[i]&(1<<k))?1:0;
                ans+=((1<<(k))*c[v^1])%mod;
                c[v]++;
            }
        }
        cout<<ans<<endl;
        return 0;
    }

    下面还有:


    然后呢?

    给定序列
    给出l,r
    求l,r之间多少个子区间异或值为k:

    传说中的莫队算法:

    #include <cstdio>
    #include <iostream>
    #include <string>
    #include <bits/stdc++.h>
    
    /*
    给定序列
    给出l,r
    求l,r之间多少个子区间异或值为k 
    */
    
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    using namespace std;
    const ll maxn = 1e5 + 6;
    ll a[maxn];
    ll ans[maxn];
    ll sum[maxn];
    ll c[maxn];
    ll n, m, k;
    ll unit;
    ll tmp;
     
    struct node {
        ll l, r, id;
    }t[maxn];
     
    ll cmp(node a, node b) {
        if (a.l / unit != b.l / unit)return a.l / unit < b.l / unit;
        return a.r < b.r;
    }
     
    void add(ll id) {
        tmp += c[a[id] ^ k];
        c[a[id]]++;
    }
     
    void dele(ll id) {
        c[a[id]]--;
        tmp -= c[a[id] ^ k];
    }
     
    void work() {
        c[0] = 1;
        ll L = 1;
        ll R = 0;
        tmp = 0;
        for (ll i = 1; i <= m; i++) {
            while (L > t[i].l) { L--; add(L - 1); }
            while (L < t[i].l) { dele(L - 1); L++; }
            while (R > t[i].r) { dele(R); R--; }
            while (R < t[i].r) { R++; add(R); }
            ans[t[i].id] = tmp;
        }
    }
     
    int main() {
        scanf("%lld%lld%lld", &n, &m, &k);
        for (ll i = 1; i <= n; i++)scanf("%lld", &a[i]),a[i]^=a[i-1];
        for (ll i = 1; i <= m; i++) {
            scanf("%lld%lld", &t[i].l, &t[i].r);
            t[i].id = i;
        }
        unit = (ll)sqrt(n);
        sort(t + 1, t + 1 + m, cmp);
        work();
        for (ll i = 1; i <= m; i++) {
            printf("%lld
    ", ans[i]);
        }
    }
  • 相关阅读:
    antd pro2.0 使用记录五:设置代理
    antd pro2.0 使用记录四:右侧顶部菜单栏+新建页面
    antd pro2.0 使用记录三:多个接口调用问题
    antd pro2.0 记录二:登录/注册页面逻辑,调用后台
    实用的Portraiture滤镜磨皮教程
    mysql 远程访问权限
    vc6.0运用mysql数据库中的编码所导致的乱码问题(接收和输出的编码必须要一致)
    飞思卡尔imx6开发板Linux下GPIO驱动
    beagleBone black 中QT的移植
    Beaglebone Black从零开始系列教程大汇总!
  • 原文地址:https://www.cnblogs.com/codemaker-li/p/9872996.html
Copyright © 2011-2022 走看看