鏈接:https://ac.nowcoder.com/acm/contest/881/H
來源:牛客網
題目描述
Bobo has a set A of n integers a1,a2,…,an.
He wants to know the sum of sizes for all subsets of A whose xor sum is zero modulo.
Formally, find mod. 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.
The second line contains n integers a1,a2,…,an.
*
*
* The number of test cases does not exceed 100.
* The sum of n does not exceed .
輸出描述:
For each test case, print an integer which denotes the result.
示例1
輸入
1
0
3
1 2 3
2
1000000000000000000 1000000000000000000
輸出
1
3
2
題目分析:
題意要求計算n個數a[1...n]中,選出若干元素構成集合S,滿足異或和爲0的集合S的大小之和。
可以將所求轉換成計算每個元素出現在異或和爲0的集合中多少次,將每個元素的次數累加起來就是答案。
做法:
個元素構造出一組線性基,構成線性基的個數暫存起來,
剩下的個數字,總共構成了個集合,
每個集合都能被線性基唯一表示出來(添加若干個基後集合異或和變爲0),
這個元素中,每個元素出現在異或和爲0的集合中的次數爲(自己在集合中,其他元素任意)
先用其他個元素構造一組線性基.
對於構成線性基的數字的計數:
複製線性基到線性基,將線性基中除了之外其他個元素加入中,
檢驗能否被所表示,若可以,答案貢獻爲(表示線性基中元素個數),
若不可以,說明與其他n-1個數字均線性無關,答案貢獻爲0
代碼:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll mod = 1e9+7;
ll poww(ll a, ll b){
ll res = 1;
while(b){
if(b&1) res = res * a %mod;
a = a*a % mod;
b >>= 1;
} return res;
}
int n;
ll a[100005];
ll r[64], b[64], p[64];
bool add(ll a[], ll x){
for(int i = 63; i >= 0; i --)
if(x & (1ll<<i)){
if(a[i])
x ^= a[i];
else{
a[i] = x;
return true;
}
}
return false;
}
int main(){
while(~scanf("%d", &n)){
vector<ll> R;
for(int i = 0; i < 64; i ++) r[i] = b[i] = 0;
int bcnt = 0;
for(int i = 1; i <= n; i++){
scanf("%lld", &a[i]);
if(add(r, a[i]))
R.push_back(a[i]);
else
bcnt += add(b, a[i]);
}
ll ans = poww(2,n-R.size()-1)*(n-R.size())%mod;
for(int i = 0; i < R.size(); i++){
memcpy(p, b, sizeof b);
int pcnt = bcnt;
for(int j = 0; j < R.size(); j++)
if(j != i) pcnt += add(p, R[j]);
if(!add(p, R[i]))
ans += poww(2,n-pcnt-1);
}
ans %= mod;
printf("%lld\n", ans);
}
return 0;
}