博弈论大作战之 PART2

来源:互联网 发布:ubuntu 17.04 cuda 编辑:程序博客网 时间:2024/04/27 15:34

HDU1536 S-Nim  

先暴力预处理所有的值得sg值,然后就是一样的。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int n,m,a,k,s[101],vis[101],sg[nMax];void init(){    sg[0]=0;    for(int i=1;i<nMax;i++) {        CLR(vis);        for(int j=0;j<k;j++) if(i-s[j]>=0) vis[sg[i-s[j]]]=1;        for(int j=0;j<101;j++) if(!vis[j]) {sg[i]=j;break;}    }}int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    while(~scanf("%d",&k),k){        FOR(i,0,k-1) scanf("%d",&s[i]);        init();        scanf("%d",&m);        string ans="";        while(m--){            scanf("%d",&n);            int SG=0;            while(n--){                scanf("%d",&a);                SG ^= sg[a];            }            if(SG) ans += "W";            else   ans += "L";        }        printf("%s\n",ans.c_str());    }    return 0;}

HDU1729 Stone Game  

看状态sg(S,S)=0,so sg(S,C)=? 设D = min{x | x*x+x >= S}; if C>=D means for (S,C) -> (S,C+1),(S,C+2),.....(S,S) so we can find that sg(S,C) = S-C; if(C<D) sg(S,C) = sg(D-1,C);

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int n,cas=1;int SG(int S,int C){    if(C==0) return 0;    int D = floor(sqrt(S+0.5));    while(D+D*D<S) D++;    if(C>=D) return S-C;    //if(C==D-1) return 0;    return SG(D-1,C);}int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    while(scanf("%d",&n),n){        int s,c,sg=0;        while(n--) {            scanf("%d%d",&s,&c);            sg ^= SG(s,c);        }        printf("Case %d:\n%s\n",cas++,sg?"Yes":"No");    }    return 0;}

HDU1730 Northcott Game

Nim游戏的变形,两个棋子之间的位置数相当于一堆nim石子,然后就。。。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    int n,m,t,s,sg=0;    while(~scanf("%d%d",&n,&m)){        sg = 0;        for(int i=0;i<n;i++) {            scanf("%d%d",&t,&s);            sg ^= ((int)fabs(t-s)-1);        }        printf("%s\n",sg?"I WIN!":"BAD LUCK!");    }    return 0;}

HDU1848 Fibonacci again and again

数据比较小,暴力处理1-1000的所有sg值,然后你懂的,异或神马的~~  不解释。。。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 1001#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int fi[200],vis[101];int sg[nMax];void init(){    int k=0;    fi[1]=1,fi[2]=2;k=3;    while(1){        fi[k]=fi[k-1]+fi[k-2];        if(fi[k]>1000) break;        k++;    }    sg[0]=0;    for(int i=1;i<=1000;i++) {        CLR(vis);        for(int j=1;j<k;j++) if(i-fi[j]>=0) vis[sg[i-fi[j]]]=1; else break;        for(int j=0;j<100;j++) if(!vis[j]) { sg[i]=j;break;}    }}int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    init();    int n,m,p;    while(scanf("%d%d%d",&n,&m,&p),n||m||p){        printf("%s\n",(sg[n]^sg[m]^sg[p])?"Fibo":"Nacci");    }    return 0;}

HDU1849 Rabbit and Grass

裸的Nim游戏。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int n,k;int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    while(scanf("%d",&n),n){        int sg=0;        while(n--) {            scanf("%d",&k);            sg ^= k;        }        printf("%s\n",sg?"Rabbit Win!":"Grass Win!");    }    return 0;}

HDU1851A Simple Game

每个游戏都是简单的巴什博弈, sg(n) = n%(m+1);

然后就是游戏和。判断一下sg就行了。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int t,n,m,l;int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    scanf("%d",&t);    while(t--){        int sg=0;        scanf("%d",&n);        while(n--){            scanf("%d%d",&m,&l);            sg ^= (m%(l+1));        }        printf("%s\n",sg?"No":"Yes");    }    return 0;}

HDU1907 John

Nim游戏的变形,吃最后一个的人输。

我们假设至少有一堆石子,那么假设当前是通常Nim游戏的必胜态,那么就是他可以取最后一个石子,但是这个人肯定有办法让这个石子被对手取到,但是如果全是1的话,就不是Nim了。

总结就是,如果有大于1的队存在,就是平常的Nim游戏,否则就是奇偶性判断的问题。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int t,n,k;int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    scanf("%d",&t);    while(t--){        scanf("%d",&n);        int sg=0,flag=0;        while(n--){            scanf("%d",&k);            sg ^= k;            if(k>1) flag=1;        }        if(flag)            printf("%s\n",sg?"John":"Brother");        else            printf("%s\n",sg==0?"John":"Brother");    }    return 0;}

HDU2509 Be the Winner

就是Nim游戏的变形,不过就是取最后一个输。。。请看上一题。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    int n,k;    while(~scanf("%d",&n)){        int SG=0,flag=0;        while(n--) {            scanf("%d",&k);            SG ^= k;            if(k>1) flag=1;        }        if(flag)            printf("%s\n",SG?"Yes":"No");        else            printf("%s\n",SG==0?"Yes":"No");    }    return 0;}

HDU3980 Paint Chain

我们先看一条链的情况,假设长度为n,每次取m个,那么sg(n,m) 就可以递归求解,当然也可以递推求解,as you like。

那么一条圈第一步是固定将他变成一条长n-m的链,于是问题就解决了。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 1001#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int n,m;int sg[nMax];int ans=0;int dfs(int n,int m){    if(sg[n]!=-1) return sg[n];    if(n<m) return sg[n]=0;    if(n==m) return sg[n]=1;    int vis[100];    CLR(vis);    for(int i=1;i<=n;i++) if(n-i-m+1>=0){        //ans = max(ans,dfs(i-1,m)^dfs(n-m-i+1,m));        vis[dfs(i-1,m)^dfs(n-m-i+1,m)]=1;    } else break;    for(int j=0;;j++) if(!vis[j]) return sg[n]=j;}int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    int t,cas=1;    for(scanf("%d",&t);t>0;t--){        scanf("%d%d",&n,&m);        printf("Case #%d: ",cas++);        if(n<m) printf("abcdxyzk\n");        else {            memset(sg,-1,sizeof(sg));            //ans=0;            if(dfs(n-m,m)==0) printf("aekdycoin\n");            else printf("abcdxyzk\n");            //cout<<ans<<endl;        }    }    return 0;}

HDU4155 The Game of 31

暴力搜索就是了,注意输入用scanf ,gets()的WA了无数次。。。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int dfs(int cur,int a[7]){    //if(cur>=31) return 0;    for(int i=1;i<7;i++) if(a[i] && cur+i<=31){        a[i]--;        if(dfs(cur+i,a)==0) {            a[i]++;            return 1;        }        a[i]++;    }    return 0;}int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    char s[130];    int a[7];    while(~scanf("%s",s)){        for(int i=1;i<7;i++) a[i]=4;        int cur=0,man=0;        while(s[man]){            cur += s[man]-'0';            a[s[man]-'0']--;            man++;        }        if(cur>=31){            printf("%s %s\n",s,man&1?"A":"B");            continue;        }        //cout<<cur<<endl;        int sg=dfs(cur,a);        if(man%2) {            printf("%s %s\n",s,sg?"B":"A");        }else {            printf("%s %s\n",s,sg==0?"B":"A");        }    }    return 0;}
HDU4203 Doubloon Game
找规律就是其PN值是K+1周期出现的。。
于是。。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int S,k;int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    int t;    scanf("%d",&t);    while(t--){        scanf("%d%d",&S,&k);        //cout<<S<<' '<<k<<endl;        S=S%(k+1);        if(k&1){            printf("%s\n",S&1?"1":"0");        }else {            if(S<k) printf("%s\n",S&1?"1":"0");            else printf("%d\n",k);        }    }    return 0;}

HDU1524 A Chess Game

无向图上的博弈,其实就是求出所有的节点的sg值。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int first[nMax],to[nMax],nxt[nMax],e;void addadge(int u,int v){    to[e]=v;nxt[e]=first[u];first[u]=e;e++;}int sg[nMax];int dfs(int u){    if(sg[u]!=-1) return sg[u];    int vis[1001];    CLR(vis);    for(int i=first[u];i!=-1;i=nxt[i]) {        vis[dfs(to[i])]=1;    }    for(int j=0;;j++) if(!vis[j]) return sg[u]=j;}int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    int n,m;    while(~scanf("%d",&n)){        memset(first,-1,sizeof(first));e=0;        for(int i=0,j,k;i<n;i++) {            scanf("%d",&j);            while(j--) {                scanf("%d",&k);                addadge(i,k);            }        }        memset(sg,-1,sizeof(sg));        while(~scanf("%d",&m),m){            int SG=0,k;            while(m--){                scanf("%d",&k);                SG ^= dfs(k);            }            printf("%s\n",SG?"WIN":"LOSE");        }    }    return 0;}

POJ2484 A Funny Game

啥都不说了,n>=3 是必败态。。。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    int n;    while(scanf("%d",&n),n){        printf("%s\n",n<=2?"Alice":"Bob");    }    return 0;}

POJ2975 Nim

nim游戏,问第一步可以做的选择,我们的目标就是转移到sg=0的点。。。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 1001#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int k[nMax],cnt,n;int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    while(scanf("%d",&n),n){        int sg = 0;        FOR(i,1,n) scanf("%d",&k[i]),sg ^= k[i];        cnt = 0;        FOR(i,1,n){            sg ^= k[i];            if(k[i]>sg)cnt++;            sg ^= k[i];        }        printf("%d\n",cnt);    }    return 0;}

POJ2234 Matches Game

将石头换成火柴的Nim游戏。。。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int n,k,sg;int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    while(~scanf("%d",&n)){        sg = 0;        while(n--){            scanf("%d",&k);            sg ^= k;        }        printf("%s\n",sg?"Yes":"No");    }    return 0;}

POJ2368 Buttons 

这道题和Ural1023是一样的,只是poj的速度比较慢一些。。所以直接暴力枚举是过不掉的。

应为k的因数一定在1-sqrt(k)之间。所以枚举这个区间就行了,但是注意因为我们枚举从三开始,所以最后还要特判k%2==0的情况。。被坑了一下下。。

Ural1023

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int k,l;int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    while(~scanf("%d",&k)){        if(k<=2) {            puts("0");            return 0;        }        int n=(int)sqrt(1.0*k+0.5);        for(l=3;l<=n+1;l++)if(k%l==0){            printf("%d\n",l-1);            return 0;        }        if(k%2==0 && k/2-1>=2) printf("%d\n",k/2-1);        else printf("%d\n",k-1);        return 0;    }    return 0;}

POJ1740 A New Stone Game

楼教主男人八题系列。。

堆数为奇数的时候必胜。

堆数为偶数且分成两份一样的时候是必败。。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 10010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int a[nMax];int n;int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    while(scanf("%d",&n),n){        CLR(a);        for(int i=0,j;i<n;i++){            scanf("%d",&j);            a[j]++;        }        if(n&1) printf("1\n");        else {            int ok=0;            for(int i=0;i<=100;i++) if(a[i]&1) {                ok=1;                break;            }            printf("%d\n",ok);        }    }    return 0;}

HDU3590 PP and QQ

好题目啊,首先是树的删边游戏,游戏的sg值是这样计算的,叶子的sg=0,中间节点的sg等于其子节点的sg+1的异或和。
其次这是一个anti-sg游戏,就是相当于nim游戏中不能操作的人嬴。用哪个号称SJ定理。

第一次试着将树什么的写成类,好有赶脚。。。

特别鸣谢aplc27出的题目。。。。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 200#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>class tree{public:    int first[nMax],to[nMax],nxt[nMax],e,sg[nMax],vis[nMax];    void clear(){memset(first,-1,sizeof(first));e=0;CLR(vis);}    void addadge(int ,int );    int dfs(int );};void tree::addadge(int u,int v){    to[e]=v;nxt[e]=first[u];first[u]=e;e++;    to[e]=u;nxt[e]=first[v];first[v]=e;e++;}int tree::dfs(int u){    sg[u]=0;    vis[u]=1;    for(int i=first[u];i!=-1;i=nxt[i])if(!vis[to[i]]){        sg[u] ^= (dfs(to[i])+1);    }    return sg[u];}tree p;int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    int n,m;    while(~scanf("%d",&n)){        int sg=0,flag=0;        FOR(i,1,n){            scanf("%d",&m);            p.clear();            for(int i=1,u,v;i<m;i++) {                scanf("%d%d",&u,&v);                p.addadge(u,v);            }            if(p.dfs(1)>1) flag=1;            sg ^= p.sg[1];        }        if(flag)            printf("%s\n",sg?"PP":"QQ");        else            printf("%s\n",sg==0?"PP":"QQ");    }    return 0;}

HDU3094 A tree game

树的删边游戏。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 200010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>class tree{public:    int first[nMax],to[nMax],nxt[nMax],e,sg[nMax],vis[nMax];    void clear(){memset(first,-1,sizeof(first));e=0;CLR(vis);}    void addadge(int ,int );    int dfs(int );};void tree::addadge(int u,int v){    to[e]=v;nxt[e]=first[u];first[u]=e;e++;    to[e]=u;nxt[e]=first[v];first[v]=e;e++;}int tree::dfs(int u){    sg[u]=0;    vis[u]=1;    for(int i=first[u];i!=-1;i=nxt[i])if(!vis[to[i]]){        sg[u] ^= (dfs(to[i])+1);    }    return sg[u];}tree p;int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    int n,m,t;    scanf("%d",&t);    while(t--){        scanf("%d",&n);        int sg=0;        p.clear();        for(int i=1,u,v;i<n;i++) {            scanf("%d%d",&u,&v);            p.addadge(u,v);        }        printf("%s\n",p.dfs(1)?"Alice":"Bob");    }    return 0;}

HUD3197 Game

树的删边游戏。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 2010#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>class tree{public:    int first[nMax],to[nMax],nxt[nMax],e,sg[nMax],vis[nMax];    void clear(){memset(first,-1,sizeof(first));e=0;CLR(vis);}    void addadge(int ,int );    int dfs(int );};void tree::addadge(int u,int v){    to[e]=v;nxt[e]=first[u];first[u]=e;e++;    to[e]=u;nxt[e]=first[v];first[v]=e;e++;}int tree::dfs(int u){    sg[u]=0;    vis[u]=1;    for(int i=first[u];i!=-1;i=nxt[i])if(!vis[to[i]]){        sg[u] ^= (dfs(to[i])+1);    }    return sg[u];}tree p;int node[nMax];int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    int n,m;    while(~scanf("%d",&n)){        int sg=0;        p.clear();m=0;        for(int i=0,v;i<n;i++) {            scanf("%d",&v);            if(v==-1) node[m++]=i;            else p.addadge(i,v);        }        for(int i=0;i<m;i++)sg ^= p.dfs(node[i]);        printf("%s\n",sg?"YES":"NO");    }    return 0;}

HUD3595 GG and MM

单个游戏的话就是哪个欧拉函数有关的游戏。

现在这个是典型的Every-SG 我们需要求出的就是传说中的step

对于单个游戏,玩家总是希望自己能够获胜的游戏玩的尽量久,而自己必败的游戏尽快输掉。于是诞生了一下的游戏步数step

step(u) = 0    if game is over

step(u) = max(step(v) | u->v and sg[v]=0 )  if sg[u]>0

step(u) = min (step(v) | u->v ans sg[v]!=0) if sg[u]==0


那么Every-SG的先手必胜就是最大的step为奇数,很神奇吧。跟多的详情请参考09年大神贾志鹏的集训队论文。。。

最后鸣谢下出题的alpc95啊。。。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 1001#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int step[nMax][nMax];int dfs(int a,int b){    step[a][b]=0;    if(b==0) return 0;    int k=a/b,ok=0;    if(dfs(b,a%b)==0){        step[a][b] = step[b][a%b]+1;        ok=1;    } else {        if(k==1) step[a][b] = step[b][a%b]+1;        else step[a][b] = step[b][a%b]+2,ok=1;    }    return ok;}int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    int n,cp;    while(~scanf("%d",&n)){        cp = -1;        for(int i=0,u,v;i<n;i++) {            scanf("%d%d",&u,&v);            if(u<v) swap(u,v);            dfs(u,v);            cp = max(cp,step[u][v]);        }        printf("%s\n",cp%2==0?"GG":"MM");    }    return 0;}

HDU2999 Stone Game, Why are you always there?

平常的nim游戏。。。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<vector>#include<set>#include<queue>#include<map>using namespace std;#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)#define CLR(a) memset((a),0,sizeof((a)))#define pb push_back#define mp make_pair#define ins insert#define F first#define S second#define bug puts("Oh Here!");#define nMax 1001#define oo 0x7fffffff#define eps 1e-8#define LL long long#define Vec vector<int>#define Pai pair<int,int>int sg[nMax];int vis[1000];int a[nMax],k,ans;void init(int n){    sg[0]=0;ans=0;    for(int i=1;i<=n;i++) {        CLR(vis);        for(int j=0;j<k;j++) {            for(int x=1;x<=i;x++) if(x+a[j]-1<=i){                //ans = max(ans,sg[x-1]^sg[i-(x+a[j]-1)]);                vis[sg[x-1]^sg[i-(x+a[j]-1)]]=1;            }else break;        }        for(int j=0;;j++) if(!vis[j]) {sg[i]=j;break;}    }    //printf("%d\n",ans);}int main(){#ifndef ONLINE_JUDGE//    freopen("input.txt","r",stdin);#endif    int n,m;    while(~scanf("%d",&k)){        FOR(i,0,k-1) scanf("%d",&a[i]);        init(1000);        scanf("%d",&m);        while(m--){            scanf("%d",&ans);            printf("%d\n",sg[ans]?1:2);        }    }    return 0;}


原创粉丝点击