题意
把Nimm游戏的任意改成每次取的数量不超过当前的一半。
题解
暴力递推SG函数的话复杂度是
O
(
n
m
2
)
O(nm^2)
O(nm2),n是堆数,m是堆的大小。稍微思考(实际上我是打表找规律发现的)可以发现,状态k和状态2k+1拥有相同的SG值,而偶数的SG值是它除以2。所以对于一个奇数,把他减1在除以2,一直到变为偶数,SG值就是这个偶数除以2。注意开始的几项不太一样,要特判。
AC代码
#include <bits/stdc++.h>
using namespace std
;
int n
;
int main()
{
int t
;scanf("%d",&t
);
for(int z
=1;z
<=t
;z
++){
scanf("%d",&n
);
int ans
=0;
for(int i
=1;i
<=n
;i
++){
int x
;scanf("%d",&x
);
int res
=0;
while(x
%2==1){
x
=(x
-1)/2;
if(x
==1){
res
=1;break;
}
}
if(x
==2){
res
=0;
}
else res
=x
/2;
ans
^=res
;
}
printf("Case %d: ",z
);
if(ans
!=0){
printf("Alice\n");
}
else printf("Bob\n");
}
return 0;
}