Nim is a mathematical game of strategy in which two players take turns removing objects from distinct heaps. On each turn, a player must remove at least one object, and may remove any number of objects provided they all come from the same heap [From Wikipedia, the free encyclopedia]. The goal of the game is to avoid being the player who doesn’t have any object to remove. The player who remove the last project is the winner.
Now KK and TT are playing Nim game with the optimal strategy. There are n heaps of stones. The number of stones in i -th heap is a i a_i ai. They play this game mm times, and KK is the player making the first move. During the i -th time they play the game on the heaps whose index in interval [ l i , r i ] [l_i,r_i] [li,ri]. KK wants to know whether he has a winning strategy or not.
The input consists of several test cases. The first line of the input gives the number of test cases, T(1≤T≤103).
For test case, the first line contains two integers n(1≤n≤10^6) and m(1≤m≤10^6), representing the number of heap of stones and the game times.
The second line contains n positive integers a 1 , a 2 , ⋯   , a n ( 1 ≤ a i ≤ 1 0 9 ) a_1,a_2,\cdots,a_n(1\le a_i\le 10^9) a1,a2,⋯,an(1≤ai≤109), representing The number of stones in i-th heap.
In the next m lines, each line contains two integers l i , r i l_i,r_i li,ri, which means the i i i within math mode i i ith game is played on the interval [ l i , r i ] [l_i,r_i] [li,ri].
It’s guaranteed that ∑ n ≤ 2 × 1 0 6 a n d ∑ m ≤ 2 × 1 0 6 \sum n\le 2\times 10^6and \sum m\le 2\times 10^6 ∑n≤2×106and∑m≤2×106.
For each test case, let $f_i $represents the answer of the i th game.
If KK has a winning strategy in the i th game then f i = 1 f_i=1 fi=1, otherwise f i = 0 f_i=0 fi=0. Please output ∑ f i ∗ 2 m − i m o d 1 0 9 + 7 \sum f_i*2^{m-i}\ mod\ 10^9+7 ∑fi∗2m−i mod 109+7,in which 1 ≤ i ≤ m 1\le i\le m 1≤i≤m.
博弈论+前缀和
对于n
个堆的Nim
游戏来说,先手必胜的条件是 a1^a2^...^a_n != 0
,所以 本题只需要求出前缀和然后计算区间异或值 num[r] ^ num[l - 1]
即可
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1000005;
const int mod = 1e9 + 7;
int num[maxn], p[maxn];
int main()
{
p[0] = 1;
for (int i = 1; i <= maxn; ++i)
p[i] = p[i - 1] * 2 % mod;//求出pow(2, i)
int T;
scanf("%d", &T);
while (T--)
{
memset(num, 0, sizeof(num));
int n, m, ans = 0;
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++i)
{
scanf("%d", &num[i]);
num[i] ^= num[i - 1];//前缀和
}
for (int i = 1; i <= m; ++i)
{
int l, r;
scanf("%d %d", &l, &r);
ans = (ans + ((num[r] ^ num[l - 1]) == 0 ? 0 : 1) * p[m - i]) % mod;
}
printf("%d\n", ans % mod);
}
return 0;
}