线性基模板

//小心全局变量a数组会被改变

void cal(int n) {

   cnt = 0;

   memset(b, 0, sizeof(b));

   for (int i = 0; i < n; ++i)

       for (int j = MAX_BASE; j >= 0; --j)

           if (a[i] >> j & 1) {

               if (b[j]) a[i] ^= b[j];

               else {

                   cnt++;

                   b[j] = a[i];

                   for (int k = j - 1; k >= 0; --k) if (b[k] && (b[j] >> k & 1)) b[j] ^= b[k];

                   for (int k = j + 1; k <= MAX_BASE; ++k) if (b[k] >> j & 1) b[k] ^= b[j];

                   break;

               }

           }

   /*

   printf("n = %d base:\n", n);

   rep(i, 0, cnt){

       printf("%d ", b[i]);

   }

   puts("");

   */

}

 

注意 b里面存的都是处理过的a, 和a不一样

 

https://blog.sengxian.com/algorithms/linear-basis


 

Codeforces 959 F Mahmoud and Ehab and yet another xor task

Discription

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

Output

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

Examples

Input

5 5

0 1 2 3 4

4 3

2 0

3 7

5 7

5 8

Output

4

2

0

4

0

Input

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.


 

4、判断:

用线性基求一个数能否被xorxor出:从高到低,对该数每个是11的位置xx,将这个数异或上axax(注意异或后这个数为1的位置和原数就不一样了),若最终变为00,则可被异或出。当然需要特判00(在构造过程中看是否有p变为0即可)。例子:(11111,10001)(11111,10001)的线性基是a5=11111a5=11111,a4=01110a4=01110,要判断1111111111能否被xorxor出,1111111111 xorxor a5a5=0=0,则这个数后来就没有是11的位置了,最终得到结果为00,说明1111111111能被xorxor出。


 

#include<bits/stdc++.h>

#define rep(i, j, k) for (int i=j; i<k; i++)

//#define pii pair<int, int>

#define fi first

#define se second

using namespace std;

const int maxn = 1e5+5;

const int MAX_BASE = 20;

const int mod = 1e9 + 7;

int n, q, cnt, last;

int a[maxn], b[MAX_BASE], pow2[maxn];

struct Query{

   int l, x, ans, id;

}query[maxn];

bool cmpl(Query a, Query b){

   return a.l < b.l;

}

bool cmpid(Query a, Query b){

   return a.id < b.id;

}

int check(int x){

   for(int i = MAX_BASE-1; i >= 0; i--){ //从高位到低位

       if ((x>>i) & 1) {

           if (((b[i] >> i) & 1) == 0) return false;

           x^=b[i];

           if (!x) return true;

       }

   }

   return true;

}

void insert(int n) {

   for (int j = MAX_BASE-1; j >= 0; --j)

       if (n >> j & 1) {

           if (b[j]) n ^= b[j];

           else {

               cnt++;

               b[j] = n;

               for (int k = j - 1; k >= 0; --k) if (b[k] && (b[j] >> k & 1)) b[j] ^= b[k];

               for (int k = j + 1; k <= MAX_BASE-1; ++k) if (b[k] >> j & 1) b[k] ^= b[j];

               break;

           }

       }

 

}

int main(){

   scanf("%d%d", &n, &q);

   pow2[0] = 1;

   rep(i, 1, n+1){

       pow2[i] = pow2[i-1] * 2 % mod;

   }

   rep(i, 0, n){

       scanf("%d", &a[i]);

   }

 

   rep(i, 0, q){

       scanf("%d%d", &query[i].l, &query[i].x);

       query[i].id = i;

   

   }

   sort(query, query+q, cmpl);

   last = 0;

   rep(i, 0, q){

       rep(j, last, query[i].l){

           insert(a[j]);

       }last = query[i].l;


 

       if (!check(query[i].x)){

           query[i].ans = 0;

           continue;

       }

 

       query[i].ans = pow2[query[i].l-cnt];

   }

   sort(query, query+q, cmpid);

   rep(i, 0, q){

       printf("%d\n", query[i].ans);

   }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值