51Nod 1067 Bash游戏 V2

题目链接:点击这里

题意:有一堆石子共有N个。A B两个人轮流拿,A先拿。每次只能拿1,3,4颗,拿到最后1颗石子的人获胜。假设A B都非常聪明,拿石子的过程中不会出现失误。给出N,问最后谁能赢得比赛。

思路:动态规划。

注意:数据有点水, 也可以通过。

AC代码:

#include
#include
#include

using namespace std;
const int N = 1e8;

bool f[N + 10];

int main()
{
    f[1] = f[3] = f[4] = true;
    f[2] = false;
    for(int i = 5; i <= N; i++)
    {
        if(f[i - 1] && f[i - 3] && f[i - 4])    f[i] = false;
        else    f[i] = true;
    }
    
    int T;
    cin >> T;
    while(T--)
    {
        int n;
        cin >> n;
        if(f[n])    puts("A");
        else    puts("B");
    }
    
    return 0;
}

上面动态规划的求解过程直观形象,但时间复杂度略高,然而本题又很难直接想出来,所以,先用SG函数打表找找规律。

打表代码:

#include
#include
#include
#include

using namespace std;
const int N = 50;

int sg[N], s[N];
int a[] = {1, 3, 4};

int main()
{
    //freopen("out.txt", "w", stdout);
    
    for(int i = 0; i < N; i++)
    {
        memset(s, 0, sizeof s);
        
        for(int j = 0; j < 3 && i - a[j] >= 0; j++) s[sg[i - a[j]]] = 1;
        
        for(int j = 0; j < N; j++)
        {
            if(!s[j])
            {
                sg[i] = j;
                break;
            }
        }
        
        printf("%d %d\n", i, sg[i]);
    }
    
    return 0;
}

打表结果:

0 0
1 1
2 0
3 1
4 2
5 3
6 2
7 0
8 1
9 0
10 1
11 2
12 3
13 2
14 0
15 1
16 0
17 1
18 2
19 3
20 2
21 0
22 1
23 0
24 1
25 2

可以发现,7的整数倍和n%7==2的是必败态。

AC代码:

#include
#include
#include
#include

using namespace std;

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n;
        scanf("%d", &n);
        if(n % 7 == 0 || n % 7 == 2)    puts("B");
        else    puts("A");
    }
    
    return 0;
}

你可能感兴趣的:(51Nod 1067 Bash游戏 V2)