This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.
#include<bits/stdc++.h>
usingnamespacestd;
constintN=55,M=50050;// M 包括了 50 * 1000 + 50个石子数量为1的堆数
intf[N][M];
intdfs(inta,intb){
int&v=f[a][b];
if(~v)returnv;
// 简单情况: 即所有堆的石子个数都是严格大于1,此时a是0
if(!a)returnv=b%2;// 奇数为先手必胜,偶数为先手必败
// 一般5个情况 + 1个特殊情况
// 特殊情况: 如果操作后出现b中只有一堆,且堆中石子个数为1
// 那么应该归入到a中,并且b为0
// 以下所有情况,如果能进入必败态,先手则必胜!
if(b==1)returndfs(a+1,0);
// 情况1:有a,从a中取一个
if(a&&!dfs(a-1,b))returnv=1;
// 情况2, 4:有b,从b中取1个(石子总数 - 1) or 合并b中两堆(堆数 - 1),
if(b&&!dfs(a,b-1))returnv=1;
// 情况3:有a >= 2, 合并a中两个
// 如果b的堆数不为0, a - 2, b + 1堆 + 2个石子(只需要加delta) ====> b + 3
// 如果b的堆数为0, a - 2, 0 + 2个石子 + 1堆 - 1 ====> b + 2
if(a>=2&&!dfs(a-2,b+(b?3:2)))returnv=1;
// 情况5:有a,有b, 合并a中1个b中1个, a - 1, b的堆数无变化 + 1个石子(只加delta)
if(a&&b&&!dfs(a-1,b+1))returnv=1;
// 其他情况,则先手处于必败状态
returnv=0;
}
intmain(){
memset(f,-1,sizeoff);
intT,n;
cin>>T;
while(T--){
cin>>n;
inta=0,b=0;
for(inti=0;i<n;i++){
intx;
cin>>x;
if(x==1)a++;
// b != 0时 加1堆 + 加x石子 = 原来的 + x + 1 (其实就是区别一开始的时候)