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;
}

浙公网安备 33010602011771号