Loading

HDU-2188 悼念512汶川大地震遇难同胞――选拔志愿者

悼念512汶川大地震遇难同胞――选拔志愿者

巴什博奕

拿到题想了老半天,感觉能超出 n 资金是个坑点,一直想不明白,就暴力打了个表,然后发现复杂度能过就交了,然后过了

后来分析发现“能超出 n 资金”这一条件完全是可有可无

  • 如果当前 n mod (m + 1) = 0:

可以直接确定先手必输,因为后手只要控制好每次都是在 n mod (m + 1) = 0 就行

  • 如果当前 n mod (m + 1) != 0:

先手可以将其转换为第一种情况

所以根据以上分析,先手必胜方完全没有必要将石子改到 n 以上

打表的方式:

#include <iostream>
using namespace std;
const int maxn = 1e5 + 20;
int sg[maxn], vis[maxn];

void get_sg(int n, int m)
{
    for(int i=0; i<=n; i++) sg[i] = 0;
    for(int i=1; i<=n; i++)
    {
        for(int j=0; j<=m; j++) vis[j] = 0;
        for(int j=max(0, i-m); j<i; j++)
            vis[sg[j]] = 1;
        for(int j=0; j<maxn; j++)
        {
            if(vis[j] == 0)
            {
                sg[i] = j;
                break;
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while(t--)
    {
        int n, m;
        cin >> n >> m;
        get_sg(n, m);
        // for(int i=0; i<=n; i++) cout << i << " sg: " << sg[i] << endl;
        bool flag = sg[n] != 0;
        for(int i=max(0, n - m); !flag && i<n; i++)
            if(sg[i] == 0) flag = true;
        if(flag) cout << "Grass" << endl;
        else cout << "Rabbit" << endl;
    }
    return 0;
}

直接取余分析:

#include <iostream>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while(t--)
    {
        int n, m;
        cin >> n >> m;
        if(n % (m + 1) == 0) cout << "Rabbit" << endl;
        else cout << "Grass" << endl;
    }
    return 0;
}
posted @ 2022-05-13 20:47  dgsvygd  阅读(19)  评论(0编辑  收藏  举报