[2019牛客网多校训练第1场]XOR

链接:https://ac.nowcoder.com/acm/contest/881/H
来源:牛客网

题目描述

Bobo has a set A of n n n integers a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,,an.
He wants to know the sum of sizes for all subsets of A whose xor sum is zero modulo ( 1 0 9 + 7 ) (10^9+7) (109+7).
Formally, find ( ∑ S ⊆ A , ⊕ x ∈ S x = 0 ∣ S ∣ ) m o d ( 1 0 9 + 7 ) (∑S⊆A,⊕x∈Sx=0|S|)mod(10^9+7) (SA,xSx=0S)mod(109+7). Note that ⊕ ⊕ denotes the exclusive-or (XOR).

输入描述:

The input consists of several test cases and is terminated by end-of-file.
The first line of each test case contains an integer n n n.
The second line contains n integers a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,,an.

  • 1 ≤ n ≤ 1 0 5 1≤n≤10^5 1n105
  • 0 ≤ a i ≤ 1 0 18 0≤a_i≤10^{18} 0ai1018
  • The number of test cases does not exceed 100 100 100.
  • The sum of n n n does not exceed 2 × 1 0 6 2×10^6 2×106.

输出描述:

For each test case, print an integer which denotes the result.

输入

1
0
3
1 2 3
2
1000000000000000000 1000000000000000000

输出

1
3
2

题意:
给定一个序列S,问这个序列的所有子序列中,子序列所有的元素的异或和为0的子序列长度和为多少?

题解:
线性基
利用期望的线性性,等价于计算每个数在集合中的方案数。
先消一次元,设会得到 r r r 个基,那么对于剩下 n − r n-r nr 个数,方案数都是 2 n – r – 1 2^{n – r – 1} 2nr1
再对除了 r r r 个基外的 n − r n-r nr 个数消个元,得到另一组基 B,枚举 r r r 个基中的一个,用另外的 r − 1 + ∣ B ∣ r-1+|B| r1+B 个数消元,会被消去的基底对答案的贡献也是 2 n – r – 1 2^{n – r – 1} 2nr1

#include
#define ll long long
#define MOD 1000000007LL
using namespace std;

int n;
ll a[100004];
ll fp(ll x,ll y){
    if(y==0)return 1LL;
    ll temp=fp(x,y>>1);
    if(y&1){
        return (((temp*temp)%MOD)*x)%MOD;
    }
    else {
        return (temp*temp)%MOD;
    }
}
struct LinearBasis{
    int sz;
    ll bs[74];
    set<int>num;
    LinearBasis(int Sz=61){
        sz=Sz;
        memset(bs,0,sizeof(bs));
        num.clear();
    }
    bool ins(ll x,int sit){
        for(ll i=sz-1,bin=(1LL<<(sz-1));i>=0;i--,bin>>=1){
            if(x&bin){
                if(!bs[i]){
                    bs[i]=x;
                    num.insert(sit);
                    break;
                }
                x^=bs[i];
            }
        }
        return x!=0;
    }
}A,B,C;

int w33ha(){
    A=LinearBasis();
    B=LinearBasis();
    C=LinearBasis();
    ll ans=0;
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        A.ins(a[i],i);
    }
    ll delta=fp(2LL,n-A.num.size()-1);
    ans=delta%MOD;
    ans=(ans*(n-A.num.size()))%MOD;
    for(int i=1;i<=n;i++){
        if(!A.num.count(i)){
            B.ins(a[i],i);
        }
    }
    for(int x:A.num){
        C=B;
        for(int y:A.num){
            if(x==y)continue;
            C.ins(a[y],y);
        }
        if(!C.ins(a[x],x)){
            ans=(ans+delta)%MOD;
        }
    }
    printf("%lld\n",ans);
    return 0;
}
int main(){
    while(scanf("%d",&n)!=EOF)w33ha();
    return 0;
}

你可能感兴趣的:(线性基)