不妨把每一堆按照石头数量从小到大排序
注意到每次只能拿一个石头,那么不论何时每堆石头的排名都是一样的
那么最终所有堆的状态一定就是 $0,1,2,...,n-1$,现在每一堆最终的石头数量都确定了
那么我们直接把每一堆的石头数量减去这一堆的排名,再加上 $1$,就得到每一堆能拿走的石头数量
那么此时就可以看成新的一些堆取石头,并且堆之间不要求不相等
显然只要没到最终状态就一定可以再拿石头
直接根据总石头数判断胜负即可
注意到如果不存在超过一对堆初始石头数量一样那么每一堆的石头数量一定不小于 $排名-1$
所以我们按上面的过程操作后不会存在某一堆石头数量为负的情况
初始时判断怎么取都有两堆一样的情况要仔细一点
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } const int N=2e5+7; ll n,a[N],sg; int main() { n=read(); for(int i=1;i<=n;i++) a[i]=read(); sort(a+1,a+n+1); ll cnt=0,val=0,zero=0; for(int i=1;i<=n;i++) zero+=a[i]==0; if(zero>1) { printf("cslnb "); return 0; }//这里要特判0!!! for(int i=2;i<=n;i++) if(a[i]==a[i-1]) cnt++,val=a[i]; for(int i=1;i<=n;i++) if(a[i]==val-1) { printf("cslnb "); return 0; } if(cnt>1) { printf("cslnb "); return 0; } for(int i=1;i<=n;i++) sg+=a[i]-i+1; if(sg&1) printf("sjfnb "); else printf("cslnb "); return 0; }