题目链接

传送门

题意

求\(n\)个数中子集内所有数异或为\(0\)的子集大小之和。

思路

对于子集大小我们不好维护,因此我们可以转换思路变成求每个数的贡献。

首先我们将所有数的线性基的基底\(b\)求出来(设秩为\(r\)),然后非基地元素的贡献就是\(2^{n-r-1}\),即选择这个数然后其他所有非基底元素都可以选择或者不选择两种方法,选择非基底元素后我们再从基底里面挑出能过把它异或为\(0\)的数选出来就可以达到题目的要求。

对于基底元素\(x\),我们将非基底的\(n-r\)个元素再跑一个线性基\(other\)出来,然后用\(b\)中除去\(x\)外的剩余元素和\(other\)构成的新的线性基\(D\)来进行选择看能不能将\(x\)消掉(理由同上),如果可以消掉那么\(x\)的贡献是\(2^{n-|D|-1}\)。

注意后面枚举\(x\)要用最初始题目给的数而不能用\(b\)中的数,反例:

\(7\) \(8\) \(6\) \(8\) \(9\) \(8\)

如果直接从基里挑会直接把\(7\)和\(6\)(的第\(2,3\)个二进制位)一起挑出来,\(6\)本来还可以提供个\(0110\)的,但是往基里一放就被7搞没了。

我说的可能不太清楚,那么可以看这篇博客~

代码实现如下

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std; typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL; #define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("D://Code//in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0) const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 1e5 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL; int n, r, tot;
bool vis[maxn];
vector<LL> vec;
LL a[maxn], b[105], other[105], tmp[105]; LL qpow(LL x, int n) {
LL res = 1;
while(n) {
if(n & 1) res = res * x % mod;
x = x * x % mod;
n >>= 1;
}
return res;
} bool ins(LL x, LL base[]) {
for(int i = 63; i >= 0; --i) {
if(x & (1LL << i)) {
if(base[i]) x ^= base[i];
else {
base[i] = x;
return true;
}
}
}
return false;
} int main() {
while(~scanf("%d", &n)) {
r = tot = 0;
vec.clear();
for(int i = 0; i <= 63; ++i) b[i] = other[i] = 0;
for(int i = 1; i <= n; ++i) {
scanf("%lld", &a[i]);
vis[i] = 0;
if(ins(a[i], b)) vis[i] = 1, ++r, vec.emplace_back(a[i]);
}
if(r == n) {
printf("0\n");
continue;
}
LL ans = qpow(2, n - r - 1) * (n - r) % mod;;
for(int i = 1; i <= n; ++i) {
if(vis[i]) continue;
ins(a[i], other);
}
for(int i = 0; i < vec.size(); ++i) {
tot = 0;
for(int j = 0; j <= 63; ++j) tmp[j] = 0;
for(int j = 0; j < vec.size(); ++j) {
if(i == j) continue;
if(ins(vec[j], tmp)) ++tot;
}
for(int j = 0; j <= 63; ++j) {
if(other[j] && ins(other[j], tmp)) ++tot;
}
if(!ins(vec[i], tmp)) {
ans = (ans + qpow(2, n - tot - 1)) % mod;
}
}
printf("%lld\n", ans);
}
return 0;
}

最新文章

  1. csharp: Download SVN source
  2. 将字符串中的URL 解析,获取内容
  3. Azure Management API 之 利用 Windows Azure Management Libraries 来控制Azure platform
  4. MySQL For Windows Zip解压版安装
  5. Fragment +ViewPager
  6. D. Ilya and Escalator
  7. External Table
  8. 两个大数相乘-Java
  9. MUI体验框架
  10. java并发包分析之———BlockingQueue
  11. iOS -- Effective Objective-C 阅读笔记 (7)
  12. swift Class的内存布局
  13. JSON:如果你愿意一层一层剥开我的心,你会发现...这里水很深——深入理解JSON
  14. 高版本sonar安装遇到的坑-sonar 6.6
  15. winform npoi excel 样式设置
  16. windows 3389 远程
  17. Leetcode_num4_Reverse Integer
  18. Android-Observer(内容观察者)
  19. Linux查看内存,负载状态
  20. 【BZOJ2199】[Usaco2011 Jan]奶牛议会 2-SAT

热门文章

  1. 一款新的好用的SSH工具——FinalShell
  2. 【idea】【sonarlint】指定文件夹扫描
  3. 【Linux】修改root密码
  4. 新唐NDA102EC1中更改UUART1作为调试串口打印输出调试信息
  5. FineUI 模板列动态删除方法
  6. Sqlserver (转载)事物与锁
  7. go标准库I/O模型:epoll+多协程
  8. SonarQube安装教程与简单使用(基于Centos7,JDK1.8)
  9. 笔记:npm常见错误
  10. SSM 前后端分离 这里controll层的返回值和之前那个不一样