zoukankan      html  css  js  c++  java
  • Luogu 4869 albus就是要第一个出场

    BZOJ 2844

    被NOIP模拟赛题弄自闭了QuQ。

    因为本题要求异或,所以自然地构造出线性基,假设本题中给出的数有$n$个,而我们构造出的线性基大小为$m$,那么每一个可以异或出来的数相当于出现了$2^{n - m}$次。

    可以把那些已经存在于异或空间中的数看成$0$,因为我们一共能凭凑出$2^m$个不同的异或值,剩下的$n - m$个数相当于可选可不选,所以每一个值有$2^{n - m}$种方案异或上一个$0$。

    然后算一算$q$在不重复的异或空间中排第几就可以了,具体做法就是把$q$用二进制表示,如果有一位$1$在线性基中存在,那么就说明剩下的数可选可不选,一共有$2^($线性基中的排名$)$个数比它小,最后还要计算$0$,需要$+1$。

    假设排名为$k$,答案就是$k*2^{n - m}$。

    时间复杂度$O(nlogn)$。

    Code:

    #include <cstdio>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    
    const int N = 1e5 + 5;
    const int M = 35;
    const ll P = 10086LL;
    
    int n, q, a[N];
    
    inline void read(int &X) {
        X = 0; char ch = 0; int op = 1;
        for(; ch > '9' || ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    namespace Lb {
        int m = 0, p[M];
        
        inline void ins(int v) {
            for(int i = 30; i >= 0; i--)
                if((v >> i) & 1) {
                    if(!p[i]) {
                        ++m;
                        p[i] = v;
                        break;
                    }
                    v ^= p[i];
                }
        }
        
    } using namespace Lb;
    
    inline ll fpow(ll x, ll y) {
        ll res = 1LL;
        for(; y > 0; y >>= 1) {
            if(y & 1) res = res * x % P;
            x = x * x % P;
        }
        return res;
    }
    
    int main() {
    //    freopen("4.in", "r", stdin);
        
        read(n);
        for(int i = 1; i <= n; i++) {
            read(a[i]);
            ins(a[i]);
        }
        read(q);
        
        int stk[M], top = 0;
        for(int i = 0; i <= 30; i++)
            if(p[i]) stk[top++] = i;
        ll ans = 0LL;
        for(int i = 0; i < top; i++)
            if((q >> stk[i]) & 1)
                ans += 1LL << i;
            
        ans %= P;
        printf("%lld
    ", (ans * fpow(2, n - top) % P + 1) % P);
        return 0;
    }
    View Code
  • 相关阅读:
    Codeforces 451A Game With Sticks
    POJ 3624 Charm Bracelet
    POJ 2127 Greatest Common Increasing Subsequence
    POJ 1458 Common Subsequence
    HDU 1087 Super Jumping! Jumping! Jumping!
    HDU 1698
    HDU 1754
    POJ 1724
    POJ 1201
    CSUOJ 1256
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9883581.html
Copyright © 2011-2022 走看看