【学习笔记】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 n1堆为 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"; } }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17529967.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(6)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示