题意:对于所有异或和为0的子集大小加和
思路:像这种异或和的我们就考虑用线性基来做,因为要求的是子集大小的总和,那我们就对于每一个数来说,来计算他的贡献。首先我们用n个数建立一个线性基a1,如果这n个数都用上了,那就说明不可能有子集异或和为0,否则,如果有r个用上了,剩下了n-r个,那就说明剩下的数都能用基内的数表示,对于没用上的数x来说,他能和外面的数搭配方案有2^(n-r-1)中,因此对于外面的数来说就有(n-r)*2^(n-r-1),对于基内的数来说,因为基内的数并不多,因此我们就可以枚举每个数,来看一下能不能通过其他数来表示,如果可以的话,他的贡献同样是2^(n-r-1)
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define ll long long
#include<queue>
#define N 0x3f3f3f3f
using namespace std;
const int maxn=1e5+10;
const int mod=1e9+7;
struct node{
ll d[65],tot;
void init()
{
memset(d,0,sizeof(d));
tot=0;
}
bool insert(ll x)
{
for(int i=62;i>=0;i--)
{
if(x&(1ll<<i))
{
if(!d[i])
{
d[i]=x;
++tot;
break;
}
x^=d[i];
}
}
return x>0;
}
}lb1,lb2,lb3;
int vis[maxn];
ll a[maxn];
ll pw[maxn];
int main(){
pw[0]=1;
for(int i=1;i<=maxn;i++)
pw[i]=pw[i-1]*2%mod;
int n;
while(scanf("%d",&n)!=EOF)
{
vector<ll> vv;
lb1.init(),lb2.init();
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
//cin>>a[i];
vis[i]=0;
if(lb1.insert(a[i]))//插入的
{
vis[i]=1;
vv.push_back(a[i]);
}
}
if(n==lb1.tot)
{
printf("0\n");
continue;
}
for(int i=1;i<=n;i++)
{
if(vis[i])continue;
lb2.insert(a[i]);
}
ll ans=(n-lb1.tot)*pw[n-lb1.tot-1]%mod;
for(int i=0;i<vv.size();i++)
{
lb3=lb2;
for(int j=0;j<vv.size();j++)
{
if(j!=i)
{
lb3.insert(vv[j]);
}
}
if(!lb3.insert(vv[i]))
{
ans=(ans+pw[n-lb1.tot-1])%mod;
}
}
printf("%lld\n",ans);
}
return 0;
}