@[toc](H题 XOR 线性基)
原文链接:here
Problem Description
求。
He wants to know the sum of sizes for all subsets of A whose xor sum is zero modulo (10^9+7).
中文意思就是求序列(序列包含个元素)中子集元素位异或值为的子集大小之和。
链接:https://ac.nowcoder.com/acm/contest/881/H
A Solution
本人太菜,忘大佬路过指出错误!
首先转换问题,这一步非常重要,他要求子集的大小之和,利用期望的线性性,其实就是要求每个元素出现在合法子集里的方案数。
我们先求出序列的一组线性基,假设***去了个元素,那么没有insert进去的元素的贡献我们可以立马得到,每个元素的贡献是,加起来就是。(按照蔡队的话说就是不在线性基里的元素xjb选
然后再来统计insert进线性基内元素的贡献。
我们重新开始,再对其他个数消个元(消元就是求线性基的过程),得到另一组线性基。
枚举这个元素,先将第一次求出的线性基中的其他个元素尝试insert入上组线性基得到线性基(也就是用另外的个数消元),如果我当前枚举的这个元素不能insert进线性基,则累加贡献。因为如果他能insert进线性基,就说明这个元素不属于线性基的张成,那就是线性无关的!所以不能算贡献。
AC_Code
#pragma comment(linker, "/STACK:102400000,102400000") #include #define fi first #define se second #define endl '\n' #define o2(x) (x)*(x) #define BASE_MAX 63 #define mk make_pair #define eb emplace_back #define all(x) (x).begin(), (x).end() #define clr(a,b) memset((a),(b),sizeof((a))) #define iis std::ios::sync_with_stdio(false); cin.tie(0) #define my_unique(x) sort(all(x)),x.erase(unique(all(x)),x.end()) using namespace std; #pragma optimize("-O3") typedef long long LL; typedef pair pii; inline LL read(){ LL x=0;int f=0;char ch=getchar(); while (ch'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x=f?-x:x; } inline void write(LL x) { if(x==0){putchar('0'),putchar('\n');return;} if(x < 0) {putchar('-');x=-x;} static char s[23];int l = 0; while(x!=0)s[l++]=x%10+48,x/=10; while(l)putchar(s[--l]); putchar('\n'); } int lowbit(int x) {return x&(-x);} template T big(const T& a1,const T& a2) { return a1>a2?a1:a2; } template T big (const T& f,const R& ...r) { return big(f, big (r...)); } template T sml(const T& a1,const T& a2) { return a1<a2?a1:a2; } template T sml (const T& f,const R& ...r) { return sml(f, sml (r...)); } void debug_out() { cerr << '\n'; } template void debug_out (const T& f,const R& ...r) { cerr << f << " "; debug_out (r...); } #define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__); #define print(x) write(x); const LL INFLL = 0x3f3f3f3f3f3f3f3fLL; const int HMOD[] = {1000000009, 1004535809}; const LL BASE[] = {1572872831, 1971536491}; const int mod = 998244353 ; const int MOD = 1e9 + 7; const int INF = 0x3f3f3f3f; const int MXN = 1e5 + 7; int n, m; LL id[MXN], bs[MXN], two[MXN], bsB[MXN]; int cnt, inBase[MXN]; LL ksm(LL a, int b) {LL res = 1;for (; b; b >>= 1, a = a * a % MOD)if (b & 1)res = res * a % MOD;return res;} bool insert(LL x, LL *bs) { for(int j = BASE_MAX; j >= 0; --j) {//63 if(!(x >> j)) continue; if(bs[j]) x ^= bs[j]; else { bs[j] = x; for(int k = j-1; k >= 0; --k) if(bs[k]&&(bs[j]&(1LL<<k))) bs[j]^=bs[k]; for(int k = j+1; k <= BASE_MAX; ++k) if(bs[k]&(1LL<<j)) bs[k]^=bs[j]; return true; } } return false; } int main() { #ifndef ONLINE_JUDGE freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin); //freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout); #endif two[0] = 1; for(int i = 1; i < MXN; ++i) two[i] = two[i-1] * 2 % MOD; while(~scanf("%d", &n)) { cnt = 0; for(int i = 0; i <= BASE_MAX; ++i) bs[i] = 0; vector baseR; for(int i = 1; i <= n; ++i) { id[i] = read(), inBase[i] = 0; if(insert(id[i], bs)) ++ cnt, inBase[i] = 1, baseR.eb(id[i]); } if(cnt == n) { printf("0\n"); continue; } LL ans = (LL)(n - cnt)*two[n - cnt - 1]%MOD; for(int i = 0; i <= BASE_MAX; ++i) bs[i] = 0; int sizB = 0; for(int i = 1; i <= n; ++i) { if(inBase[i]) continue; if(insert(id[i], bs)) ++ sizB; } // debug(ans) int tmp = sizB; for(auto x: baseR) { memcpy(bsB, bs, sizeof(LL)* 64); sizB = tmp; for(auto y: baseR) { if(x != y && insert(y, bsB)) ++ sizB; } if(!insert(x, bsB)) ans = (ans + two[n-sizB-1]) % MOD; // debug(flag, sizB) } printf("%lld\n", (ans+MOD)%MOD); } #ifndef ONLINE_JUDGE cout << "time cost:" << (double)clock()/CLOCKS_PER_SEC << "ms" << endl; #endif return 0; } /* 1 0 3 1 2 3 2 1000000000000000000 1000000000000000000 1 3 2 */