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;
}