【学习笔记】BZOJ3859 取石子
首先,如果不存在数目为 1 1 1的石子堆,设 n n n为石子堆数, m m m为石子总的数目,那么当 n + m n+m n+m为偶数时先手必胜, n + m n+m n+m为奇数时后手必胜。
如果存在数目为 1 1 1的石子堆,我尝试进行等效替代,但是好像不太行。那就直接来看吧,操作大小为 1 1 1的石子堆相当于操作了两次,那么会导致胜负反转,如果初始大小为 1 1 1的石子堆有偶数个那么对胜负不会造成影响,否则会对胜负造成影响。但是看样例也很容易看出来全为 1 1 1是一个特殊情况,特殊情况特殊处理即可。
这题的特殊情况也非常狗屎。结论是当 3 ∣ n 3|n 3∣n时后手必胜。有 n − 1 n-1 n−1堆为 1 1 1,剩下一堆为 2 2 2的情况也要特判。我不想解释。
另一个比较巧妙的思路是直接看大小为 1 1 1的石子堆数目的奇偶性。当大小为 1 1 1的石子堆数目为 1 1 1时先手必胜,为 2 2 2时为了保证不必败一定是将两个大小为 1 1 1的石子堆合并起来,那么就是按不存在大小为 1 1 1的石子堆的情况去判,那么可以归纳证明当为奇数时先手必胜,为偶数时看 n + m n+m n+m的奇偶性。
反正我瞎写了一个讨论也过了。比较高消。
#include<bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
using namespace std;
int T,n,m,ones,a[55];
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>T;
while(T--){
cin>>n,m=n,ones=0;for(int i=1;i<=n;i++)cin>>a[i],m+=a[i],ones+=(a[i]==1);
if(ones==n){
if(n%3==0)cout<<"NO";
else cout<<"YES"<<"\n";
}
else if(ones==n-1&&m==2*n+1){
if(n%3==0||n%3==2)cout<<"YES"<<"\n";
else cout<<"NO"<<"\n";
}
else if(ones%2==1)cout<<"YES"<<"\n";
else if(m%2==0)cout<<"YES"<<"\n";
else cout<<"NO"<<"\n";
}
}

浙公网安备 33010602011771号