loj&codeforces 线性基

              F. Mahmoud and Ehab and yet another xor task
time limit per test
1 second
memory limit per test
512 megabytes
input
standard input
output
standard output

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.

Input

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 ≤ n0 ≤ x < 220), representing the queries.

Output

For each query, output its answer modulo 109 + 7 in a newline.

Examples
input
Copy
5 5
0 1 2 3 4
4 3
2 0
3 7
5 7
5 8
output
4
2
0
4
0
input
Copy
3 2
1 1 1
3 1
2 0
output
4
2
Note

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

  

原文地址:https://www.cnblogs.com/wang9897/p/8719209.html