牛客练习赛67 C-牛牛爱博弈(SG打表)

题目链接:https://ac.nowcoder.com/acm/contest/6885/C
CSDN食用链接:https://blog.csdn.net/qq_43906000/article/details/108019486

题目描述

牛牛和牛妹玩博弈游戏。
牛牛:我们来玩取石子游戏。一共有n堆石子,每个人每次可以取1或2颗石子,谁取走了最后一颗石子就算谁获胜。
牛妹:这游戏太无聊了。
牛牛:那改一改。一共有n堆石子,每个人每次可以取\(1,2,4,8,...2^k\)颗石子,谁取走了最后一颗石子就算谁获胜。
牛妹:好的,你先开始取吧。
牛牛心里知道自己是否有必胜策略,但他想来考考你。
因为牛牛和牛妹很爱玩这种游戏,所以本题有多组数据。
(注:牛牛叫\(\color{grey}{Alan}\),牛妹叫\(\color{black}{F}\color{red}{rame}\).)

输入描述:
第一行,输入数据组数T。
接下来T行,每行一个数n。

输出描述:
对于每一组数据,
如果牛牛必胜,则输出“Alan”(不含引号);
如果牛妹胜,则输出“Frame”(不含引号)。
(PS:牛牛叫 Alan ,牛妹叫 Frame )

输入
3
1
2
3

输出
Alan
Alan
Frame

说明
当n=1时,牛牛直接取1颗石子即可获胜。
当n=2时,牛牛直接取2颗石子即可获胜。
当n=3时,显然牛牛论怎么取,牛妹都可以获胜。

输入
3
17
18
19

输出
Alan
Frame
Alan
备注:
数据保证\(1\le T\le 1000,1\le n\le 2\times 10^9\)

emmm,这题和HDU1847有些类似,只不过这题的数据比较大而已,所以我们可以直接用SG打表看看规律,其打表程序如下:

#include <bits/stdc++.h>
using namespace std;
 
#define ll long long
const int mod = 1e6;
const int mac = 1e5 + 10;
const int inf = 1e8 + 10;
int f[60], num = 0;
int sg[1005], s[1005];
vector<int>a,b;
void SG(int n)
{
    memset(sg, 0, sizeof(sg));
    for (int i = 1; i <= n; i++) {
        memset(s, 0, sizeof s);
        for (int j = 1; f[j] <= i && j <= num; j++) 
            s[sg[i - f[j]]] = 1;
        for (int j=0;;j++)
            if (!s[j]) { sg[i] = j; break; }
    }
}
int main()
{
    int n;
    for (int i = 1; i <= 1000; i *= 2) {
        f[++num] = i;
    }
    SG(1000);
    for (int i=1; i<=1000; i++)
        if (sg[i]==0) a.push_back(i);
        else b.push_back(i);
    for (auto v:a) printf("%d ",v );printf("\n");
    for (auto v:b) printf("%d ",v );printf("\n");
    return 0; 
}

最后打出的表如下:
在这里插入图片描述
那么我们就很容易看出其规律。
以下是AC代码:

#include <bits/stdc++.h>
using namespace std;

const int mac=1e5+10;
int a[mac];

int main()
{
    int t;
    scanf ("%d",&t);
    while (t--){
        int n;
        scanf ("%d",&n);
        if (n%3==0) printf ("Frame\n");
        else printf ("Alan\n");
    }
}
posted @ 2020-08-15 11:05  lonely_wind  阅读(204)  评论(0编辑  收藏  举报