转载自:http://blog.csdn.net/sr_19930829/article/details/23446173
解题思路:
这个题折腾了两三天,参考了两个模板,在这之间折腾过来折腾过去,终于把用法和需要注意的地方弄清楚了,汗。注意的是: bool类型的数组比int类型的数组快,不超时与超时的区别,在sg组合博弈时,只能在(a1,a2,a3,a4)中取,要特别注意这里面的数字是否是有序的,这个特别重要,下面贴出的两个模板对应了两种情况。最后,大数据输入还得用scanf。。
模板1(该模板注意的是一定要把 f 数组中的数字从小到大排序):
const int N=10008;//N为所有堆最多石子的数量 int f[108],sg[N];//f[]用来保存只能拿多少个,sg[]来保存SG值 bool hash[N];//mex{} void sg_solve(int t,int N)//t指f[]中的个数 { int i,j; memset(sg,0,sizeof(sg)); for(i=1;i<=N;i++) { memset(hash,0,sizeof(hash)); for(j=1;j<=t&&f[j]<=i;j++) { hash[sg[i-f[j]]]=1; } for(j=0;j<=N;j++) if(!hash[j]) break; sg[i] = j; } }
模板2(该模板不需要进行排序)
const int N=10008;//N为所有堆最多石子的数量 int f[108],sg[N];//f[]用来保存只能拿多少个,sg[]来保存SG值 bool hash[N];//mex{} void sg_solve(int t,int N) { int i,j; memset(sg,0,sizeof(sg)); for(i=1;i<=N;i++) { memset(hash,0,sizeof(hash)); for(j=1;j<=t;j++) if(i - f[j] >= 0) hash[sg[i-f[j]]] = 1; for(j=0;j<=N;j++) if(!hash[j]) break; sg[i] = j; } }
代码(使用第二个模板)
#include <iostream> #include <algorithm> #include <stdio.h> #include <string.h> using namespace std; const int N=10008;//N为所有堆最多石子的数量 int f[108],sg[N];//f[]用来保存只能拿多少个,sg[]来保存SG值 bool hash[N];//mex{} void sg_solve(int t,int N) { int i,j; memset(sg,0,sizeof(sg)); for(i=1;i<=N;i++) { memset(hash,0,sizeof(hash)); for(j=1;j<=t;j++) if(i - f[j] >= 0) hash[sg[i-f[j]]] = 1; for(j=0;j<=N;j++) if(!hash[j]) break; sg[i] = j; } } int main() { int k,m,l,num,i,j; while(scanf("%d",&k),k) { for(i=1;i<=k;i++) scanf("%d",&f[i]); sg_solve(k,N); scanf("%d",&m); string ans=""; for( i=1;i<=m;i++) { int sum=0; scanf("%d",&l); for( j=1;j<=l;j++) { scanf("%d",&num); sum^=sg[num]; } if(sum==0) ans+="L"; else ans+="W"; } cout<<ans<<endl; } return 0; }