题目大意
有\(n\)堆糖果,第\(i\)堆有\(a_i\)个。
两个人轮流决策,决策分为两种:
1.选择糖果数最多的一堆糖果,并把这堆糖全吃了。
2.在每堆非空的糖果堆里拿一颗糖吃掉。
吃掉最后一颗糖的人输。问你先手必胜还是先手必败。
\(n\leq 100000\)
题解
又是一个打表结论题。
先把\(a_i\)从大到小排序。
设\(f_{i,j}\)为删掉前\(i\)大,每堆删掉\(j\)个后是先手必胜还是先手必败。先把所有的\(f_{i,j}\)算出来。
如果都删完了,就先手必胜。
打个表可以发现,一条斜线上的结果相同。
这个结论还是挺好证的。这里就不证了。
直接找到\((0,0)\)对应的是哪个点\((i,i)\),算出这个点到上方和右方轮廓的距离,只要有一个是偶数,就先手必胜。
时间复杂度:\(O(n)\)
代码
#include#include #include #include #include #include using namespace std;typedef long long ll;typedef unsigned long long ull;typedef pair pii;int a[100010];int main(){#ifdef DEBUG freopen("b.in","r",stdin); freopen("b.out","w",stdout);#endif int n; int i; scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+n+1,greater ()); int ans; a[0]=a[1]; for(i=0;i<=n;i++) if(a[i+1]<=i) { ans=(a[i]-i)&1; int j=i+1; while(j<=n&&a[j]==i) j++; if((j-i+1)&1) ans=1; break; } if(ans) printf("First\n"); else printf("Second\n"); return 0;}