因为第i个瓶子里的所有豆子都是等价的,设sg(i)表示第i个瓶子的sg值,可以转移到sg(j)^sg(k)(i<j<n,j<=k<n)的状态。
只需要考虑豆子数是奇数的瓶子啦,因为如果豆子数是偶数,重复异或是没有意义的。
对于方案数什么的……枚举就好了。
#include<cstdio> #include<cstring> #include<set> using namespace std; int T,n,a[21],SG[21]; int sg(int x) { if(SG[x]!=-1) return SG[x]; set<int>S; for(int i=x+1;i<n;++i) for(int j=i;j<n;++j) S.insert(sg(i)^sg(j)); for(int i=0;;++i) if(S.find(i)==S.end()) return SG[x]=i; } int main() { scanf("%d",&T); for(;T;--T) { memset(SG,-1,sizeof(SG)); int ans=0,sum=0; scanf("%d",&n); for(int i=0;i<n;++i) { scanf("%d",&a[i]); if(a[i]&1) ans^=sg(i); } if(ans) { for(int i=0;i<n;++i) if(a[i]) for(int j=i+1;j<n;++j) for(int k=j;k<n;++k) { --a[i]; ++a[j]; ++a[k]; int t=0; for(int l=0;l<n;++l) if(a[l]&1) t^=sg(l); if(!t) { ++sum; if(sum==1) printf("%d %d %d\n",i,j,k); } ++a[i]; --a[j]; --a[k]; } printf("%d\n",sum); } else printf("-1 -1 -1\n0\n"); } return 0; }
时间: 2024-12-30 03:57:20