bzoj 1188 SG函数
首先我们可以把一个石子看成一个单独的游戏,那么我们可以发现所有位置的石子至于奇偶有关,因为某一个人操作其中的一个石子,我们可以用相同的石子做相同的操作,所以我们只需要保留下所有位置的01,那么对于每个位置的sg函数值,我们需要枚举之后所有可能放的情况就可以了。然后我们就可以判断是否先手必胜,然后对于方案,我们就枚举取哪一个向哪儿放,求出来之后的sg值,要是先手必败的话,这个方案就是先手必胜的,累加答案就好了。
/************************************************************** Problem: 1188 User: BLADEVIL Language: C++ Result: Accepted Time:0 ms Memory:804 kb ****************************************************************/ //By BLADEVIL #include <cstdio> #include <cstring> #define maxn 30 using namespace std; int flag[100],sg[maxn],a[maxn]; void prepare() { for (int i=1;i<=25;i++) { int j; memset(flag,0,sizeof flag); for (j=1;j<i;j++) for (int k=1;k<i;k++) flag[sg[j]^sg[k]]=1; for (j=0;flag[j];j++); sg[i]=j; } } void solve() { int n; scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); int ans=0; for (int i=1;i<=n;i++) if (a[i]&1) ans^=sg[n-i+1]; if (!ans) {printf("-1 -1 -1\n0\n");return;} int ans1,ans2,ans3,kind; ans1=ans2=ans3=kind=0; for (int i=1;i<=n;i++) for (int j=i+1;j<=n;j++) for (int k=j;k<=n;k++) if (!(ans^sg[n-i+1]^sg[n-j+1]^sg[n-k+1])) if (!kind++) ans1=i,ans2=j,ans3=k; printf("%d %d %d\n%d\n",ans1-1,ans2-1,ans3-1,kind); } int main() { prepare(); int task; scanf("%d",&task); while (task--) solve(); return 0; }