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