一年前的博文了。时间过得真快啊~~~现在又不会SG了。
一直觉得博弈是一个很是神秘的东西,现在在看博弈,觉得很是有趣,尤其是SG函数,昨天今天做了几道题,尤其 是上周的多校给了我很多不一样的东西。开始的时候做的是HDU上的两道取石子的题目。基本上都是给你几堆石子然后有规定你只能取几颗什么的。多校的那道题我按同样的思路来写WA掉了,现在才终于理解所谓的前继后继。明明是很明显的一个点总是会出现在我视线的盲区。对于其他概念的理解也是这样,让我觉得小不爽,但是好歹是对SG的了解更加深了一步。。噢~~~~附上hdu上三道题的解法,其中两道都分别用DFS和打表写了一遍~~
hdu1536:
(dfs版)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int s[110],a[110][110],min,k,l,sg[10010];
int sgfun(int n){
int i,mex[101];
memset(mex,0,sizeof(mex));
for(i=1;i<=k;i++){
if(n>=s[i]){
if(sg[n-s[i]]==-1)
sg[n-s[i]]=sgfun(n-s[i]);
mex[sg[n-s[i]]]=1;
}
else
break;
}
for(i=0;mex[i];i++);
return i;
}
main(){
int i,j,ans;
memset(sg,-1,sizeof(sg));
while(scanf("%d",&k)!=-1 && k){
//printf("pp\n");
memset(sg,-1,sizeof(sg));
for(i=1;i<=k;i++){
scanf("%d",&s[i]);
}
//printf("pp\n");
sort(s+1,s+k+1);
scanf("%d",&l);
//ans=1;
//printf("pp\n");
for(i=1;i<=l;i++){
scanf("%d",&a[i][0]);
//printf("pp\n");
for(j=1;j<=a[i][0];j++){
scanf("%d",&a[i][j]);
//memset(mex,0,sizeof(mex));
if(sg[a[i][j]]==-1)
sg[a[i][j]]=sgfun(a[i][j]);
if(j==1){
ans=sg[a[i][j]];
}
else{
ans^=sg[a[i][j]];
}
}
if(ans)
printf("W");
else
printf("L");
}
printf("\n");
}
}
(打表版)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int s[110],a[110][110],min,k,l,mex[10010],sg[10010];
void sgfun(){
int i,mex[101],j,p;
sg[0]=0;
for(i=1;i<10001;i++){
j=1;
memset(mex,0,sizeof(mex));
while(j<=k && i>=s[j]){
mex[sg[i-s[j]]]=1;
j++;
}
j=0;
while(mex[j]){
j++;
}
sg[i]=j;
}
}
main(){
int i,j,ans;
//memset(sg,-1,sizeof(sg));
//sgfun();
while(scanf("%d",&k)!=-1 && k!=0){
//printf("pp\n");
//memset(sg,-1,sizeof(sg));
for(i=1;i<=k;i++){
scanf("%d",&s[i]);
}
//printf("pp\n");
sort(s+1,s+k+1);
sgfun();
scanf("%d",&l);
//ans=1;
//printf("pp\n");
for(i=1;i<=l;i++){
scanf("%d",&a[i][0]);
//printf("pp\n");
ans=0;
for(j=1;j<=a[i][0];j++){
scanf("%d",&a[i][j]);
//memset(mex,0,sizeof(mex));
//if(sg[a[i][j]]==-1)
//sg[a[i][j]]=sgfun(a[i][j]);
ans^=sg[a[i][j]];
}
if(ans)
printf("W");
else
printf("L");
}
printf("\n");
}
}
hdu1848:
(打表版)
#include<cstdio>
#include<cstring>
using namespace std;
int mex[1001],sg[1001],f[20];
void fibo(){
int i;
f[0]=1;f[1]=1;
for(i=2;i<=16;i++)
f[i]=f[i-1]+f[i-2];
}
/*int sgfun(int n){
int i;
memset(mex,0,sizeof(mex));
for(i=1;i<=16;i++){
if(n>=f[i]){
if(sg[n-f[i]]==-1)
sg[n-f[i]]=sgfun(n-f[i]);
mex[sg[n-f[i]]]=1;
}
else
break;
}
for(i=0;mex[i];i++);
return i;
}*/
void sgfun(){
int i,mex[101],j;
sg[0]=0;
for(i=1;i<1001;i++){
j=1;
memset(mex,0,sizeof(mex));
while(j<=16 && i>=f[j]){
mex[sg[i-f[j]]]=1;
j++;
}
j=0;
while(mex[j]){
j++;
}
sg[i]=j;
}
}
main(){
int n,m,p,ans;
fibo();
memset(sg,-1,sizeof(sg));
sgfun();
while(scanf("%d%d%d",&n,&m,&p)!=-1 && !(n==0 && m==0 && p==0)){
//if(sg[n]==-1)
//sg[n]=sgfun(n);
//if(sg[m]==-1)
//sg[m]=sgfun(m);
//if(sg[p]==-1)
//sg[p]=sgfun(p);
ans=sg[n];
ans^=sg[m];
ans^=sg[p];
//printf("%d %d %d\n",sg[n],sg[m],sg[p]);
//printf("%d\n",ans);
if(ans)
printf("Fibo\n");
else
printf("Nacci\n");
}
}
(dfs)
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
using namespace std;
int sg[1001],f[20];
void fibo(){
int i;
f[0]=1;f[1]=1;
for(i=2;i<=16;i++)
f[i]=f[i-1]+f[i-2];
}
int sgfun(int n){
int i,mex[1001];
memset(mex,0,sizeof(mex));
for(i=1;i<=16;i++){
if(n>=f[i]){
if(sg[n-f[i]]==-1)
sg[n-f[i]]=sgfun(n-f[i]);
mex[sg[n-f[i]]]=1;
}
else
break;
}
for(i=0;mex[i];i++);
return i;
}
main(){
int n,m,p,ans;
fibo();
memset(sg,-1,sizeof(sg));
//sgfun();
while(scanf("%d%d%d",&n,&m,&p)!=-1 && !(n==0 && m==0 && p==0)){
if(sg[n]==-1)
sg[n]=sgfun(n);
if(sg[m]==-1)
sg[m]=sgfun(m);
if(sg[p]==-1)
sg[p]=sgfun(p);
ans=sg[n];
ans^=sg[m];
ans^=sg[p];
//printf("%d %d %d\n",sg[n],sg[m],sg[p]);
//printf("%d\n",ans);
if(ans)
printf("Fibo\n");
else
printf("Nacci\n");
}
}
hdu3975