博弈论大作战之 PART2

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值