[SG函数]吃吃吃
Description
桌上摆着NN坨糖果(不要吐槽量词),分别标号为1~N,一开始时第ii坨糖果里有aiai颗糖。
すぬけ君和青木君准备用这N坨糖玩一个游戏。他们轮流操作,すぬけ先手。每一次操作,必须从以下两种操作中选一个执行:
1. 选择糖果数最多的一坨糖果,并把这坨糖全吃了。
2. 在每坨非空的糖果堆里拿一颗糖吃掉。
吃掉最后一颗糖的人将输掉游戏。假设这两个人都足够ниуби(都会选择最优策略),请你算出哪个人最终会取得胜利。
すぬけ君和青木君准备用这N坨糖玩一个游戏。他们轮流操作,すぬけ先手。每一次操作,必须从以下两种操作中选一个执行:
1. 选择糖果数最多的一坨糖果,并把这坨糖全吃了。
2. 在每坨非空的糖果堆里拿一颗糖吃掉。
吃掉最后一颗糖的人将输掉游戏。假设这两个人都足够ниуби(都会选择最优策略),请你算出哪个人最终会取得胜利。
Input
输入第一行包含一个整数NN,第二行包含NN个整数a1,a2,...,aN。
Output
如果すぬけ最终能获胜,输出"First",否则输出"Second"。
Sample Input
## Sample Input 1
2
1 3
## Sample Input 2
3
1 2 1
## Sample Input 3
3
1 2 3
Sample Output
## Sample Output 1
First
## Sample Output 2
First
## Sample Output 3
Second
HINT
1≤N≤1e5
1≤ai≤1e9
有40分的子任务满足1≤N,ai≤2000
分析
从大到小排序后把糖果画成条形图,容易发现操作其实是在取走最左一列或最下一行
然后DP打个表可以发现对角线的SG值相等
然后我们只需要找到经过0,0的对角线在图形上的最后一个交点,其上方糖果数或右方糖果数为偶即可获胜
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int N=1e5+10; int a[N],n; bool CMP(int a,int b) {return a>b;} int main() { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+n+1,CMP); for (int i=1,j;i<=n;i++) if (a[i+1]<i+1) { for (j=i;i==a[j+1];j++); printf((((j-i)&1)|((a[i]-i)&1))?"First":"Second"); return 0; } }
在日渐沉没的世界里,我发现了你。