NEUQ 2013 Nim Game

Description

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.

Input

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(1ai109), 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 n2×106andm2×106

Output

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 fi2mi mod 109+7,in which 1 ≤ i ≤ m 1\le i\le m 1im


博弈论+前缀和

对于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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值