loj&codeforces 线性基
Ehab has an array a of n integers. He likes the bitwise-xor operation and he likes to bother Mahmoud so he came up with a problem. He gave Mahmoud q queries. In each of them, he gave Mahmoud 2 integers l and x, and asked him to find the number of subsequences of the first l elements of the array such that their bitwise-xor sum is x. Can you help Mahmoud answer the queries?
A subsequence can contain elements that are not neighboring.
The first line contains integers n and q (1 ≤ n, q ≤ 105), the number of elements in the array and the number of queries.
The next line contains n integers a1, a2, ..., an (0 ≤ ai < 220), the elements of the array.
The next q lines, each contains integers l and x (1 ≤ l ≤ n, 0 ≤ x < 220), representing the queries.
For each query, output its answer modulo 109 + 7 in a newline.
5 5
0 1 2 3 4
4 3
2 0
3 7
5 7
5 8
4
2
0
4
0
3 2
1 1 1
3 1
2 0
4
2
The bitwise-xor sum of the empty set is 0 and the bitwise-xor sum of a set containing one element is that element itself.
首先线性基有个很好的性质 对于一个数 用基地能够唯一表示 也就是说判断有多少个数异或能形成这个数 只需要确定出这个集合能异或出多少个 然后取组合数就行了 ...从而这个题就能转换成 线性基 来判断是否有解还是无解 以及这个区间能形成多少个0即可
#include <bits/stdc++.h> #define ll long long #define s second #define f first const int mod=1e9+7; #define pii pair<ll,int> const int MAXN=1e5+10; using namespace std; ll vis[25]; ll a[MAXN]; vector<pii> vec[MAXN]; ll ans[MAXN]; ll ksm(int m){ ll ans1=1;ll t=2; while(m){ if(m&1) ans1=ans1*t%mod; m=m>>1;t=t*t%mod; } return ans1; } int main(){ ios::sync_with_stdio(false); int n,m,l;ll x;cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=m;i++){ cin>>l>>x; vec[l].push_back(make_pair(x,i)); } int cnt=0; memset(ans,0,sizeof(ans)); for(int i=1;i<=n;i++){ for(int j=20;j>=0;j--){ if((a[i]&(1<<j))){ if(vis[j]) a[i]^=vis[j]; else{ vis[j]=a[i];break; } } } if(a[i]==0) cnt++; for(int j=0;j<vec[i].size();j++){ x=vec[i][j].f;bool flag=0; for(int k=20;k>=0;k--){ if((x&(1<<k))){ if(vis[k]) x^=vis[k]; else{ flag=1;break; } } } if(!flag) ans[vec[i][j].s]=ksm(cnt); } } for(int i=1;i<=m;i++) cout<<ans[i]<<endl; return 0; }
loj 113
线性基模板题 ...求最大异或和 有个贪心的思想 就是说如果能从高位向地位异或 直到值不增加即可 最小值就是最低位的值
#include <bits/stdc++.h> #define ll long long using namespace std; ll vis[55];ll a[55]; int main(){ int n;cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++){ for(int j=50;j>=0;j--){ if(a[i]&((1ll<<j))){ if(vis[j]) a[i]^=vis[j]; else{ vis[j]=a[i];break; } } } } ll ans=0; for(int i=50;i>=0;i--){ if(!vis[i]) continue; if((ans^vis[i])>ans) ans^=vis[i]; } cout<<ans<<endl; return 0; }
loj 114
线性基模板题 求第K小 意思可以对于线性基变形重构 成每一位只有当前位置为1 把低位用线性基异或掉 也就是说在把第k二进制分解 为1的位异或上相应的线性基即可 但是有个坑点 就是必须要考虑0的情况 特判查找即可
#include <bits/stdc++.h> #define ll long long const int MAXN=1e5+10; using namespace std; ll vis[65],a[MAXN],d[65];int cnt; ll work(ll k){ if(k>=(1ll<<cnt)) return -1; ll ans=0; for(int i=cnt-1;i>=0;i--){ if(k&(1ll<<i)) ans^=d[i]; } return ans; } int main(){ int n;cin>>n;int flag=0; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++){ for(int j=60;j>=0;j--){ if(a[i]&(1ll<<j)){ if(vis[j]) a[i]^=vis[j]; else{ vis[j]=a[i];break; } } } if(!a[i]) flag=1; } for(int i=60;i>=0;i--){ for(int j=i-1;j>=0;j--){ if(vis[i]&(1ll<<j)){ vis[i]^=vis[j]; } } } cnt=0; for(int i=0;i<=60;i++){ if(vis[i]) d[cnt++]=vis[i]; } int m;cin>>m;ll k; for(int i=1;i<=m;i++){ cin>>k; if(flag) k--; cout<<work(k)<<endl; } return 0; }