其他分享
首页 > 其他分享> > HDU 3404 Switch light (Nim积)

HDU 3404 Switch light (Nim积)

作者:互联网

原文链接:https://blog.csdn.net/kele52he/article/details/77099890

题面:

lxhgww is playing a game with his computer Deep Blue. The game is played on a matrix containing lights. At first, some lights are on, while others are off. lxhgww and Deep Blue take turns to switch the lights. For each step, the player should choose a rectangle in the matrix: (x1, y1) , (x1, y2) , (x2, y1) , (x2, y2) , (x1 <= x2, y1 <= y2, the light at (x2, y2) should be on) and change the lights’ status on the four vertex of the rectangle, namely on to off, and off to on. The player turns all the lights off wins the game. Notice the rectangle is possibly degenerated to line or even a single cell so that the player may also switch two or one besides four lights in a move. Deep Blue’s strategy is perfect, if it has a chance to win, never will it lose. Does lxhgww have a chance to win if he takes the first step?

Input

The first line is an integer T(T<=100) indicating the case number.
Each case has one integers n (n<= 1000 ), the number of on-lights at the beginning of the game.
Then come n lines, each line has two integers, xi , yi, (1<=xi<=10000, 1<=yi<=10000) , so light at (xi, yi) is on at first. (No two lights at the same position)

Output

If lxhgww still has a chance to win, output “Have a try, lxhgww.”, otherwise tell lxhgww “Don’t waste your time.”

Sample Input

2
2
1 2
2 1
2
1 1
2 2

Sample Output

Don’t waste your time.
Have a try, lxhgww.

解:

这是一道Nim积的模板题,可是查了好多东西只有一篇论文比较详细讲了Nim积,可惜的是看到一半就懵了。
论文:http://www.doc88.com/p-5098170314707.html

#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstring>
using namespace std;

typedef long long ll;
const int N  = 1e4+10;

int sg[20][20];

int nimmul(int x, int y);

int nimpow(int x, int y)//计算2^x和2^y的nim积
{
    if(sg[x][y] != -1)
        return sg[x][y];
    if(!x)//1与2^y的nim积
        return sg[x][y] = 1 << y;
    if(!y)//1与2^x的nim积
        return sg[x][y] = 1 << x;
    int ans = 1, k = 1, x1 = x, y1 = y, t;
    while(x || y)//将x和y分解为二进制,计算普通乘积的,即对应二进制位不同的
    {
        t = 1 << k;
        if((x & 1 || y & 1) && !((x & 1) && (y & 1)))//该位不同
            ans *= t;
        x >>= 1;
        y >>= 1;
        k <<= 1;//从此位得到指数(指数也是2的幂)
    }
    k = 1;
    x = x1;
    y = y1;
    while(x || y)//计算相同的费马数,与已得出的数的nim积
    {
        t = 1 << k;
        if((x & 1) && (y & 1))//该位相同
            ans = nimmul(ans, t/2*3);
        x >>= 1;
        y >>= 1;
        k <<= 1;//从此位得到指数(指数也是2的幂)
    }
    return (sg[x1][y1] = ans);
}

int nimmul(int x, int y)
{
    if(!x || !y)
        return 0;
    if(x == 1)
        return y;
    if(y == 1)
        return x;
    int ans = 0;
    for(int i = x, a = 0; i; i >>= 1, a++)//将x和y分解后按分配律计算积
    {
        if((i & 1) == 0)//该二进制位是1才计算,否则跳过
            continue;
        for(int j = y, b = 0; j; j >>= 1, b++)
        {
            if((j & 1) == 0)
                continue;
            ans ^= nimpow(a, b);
        }
    }
    return ans;
}

int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        memset(sg, -1, sizeof(sg));
        int n;
        cin >> n;
        int x, y, ans = 0;
        for(int i = 0; i < n; ++i)
        {
            scanf("%d%d", &x, &y);
            ans ^= nimmul(x, y);
        }
        if(ans)
            printf("Have a try, lxhgww.\n");
        else
            printf("Don't waste your time.\n");
    }
    return 0;
}

标签:HDU,include,int,light,lights,Switch,ans,lxhgww,sg
来源: https://blog.csdn.net/xiaobian_/article/details/97893213