首页 > 博弈论一点点

博弈论一点点

基本就是把这里的题过了一遍

SG函数资料(入门必备)

感觉很不错的文章

博弈论(一):Nim游戏

博弈论(二):Sprague-Grundy函数

寻找必败态——一类博弈问题的快速解法

练手

hdu1846

#include
using namespace std;
int main(){int T,n,m;scanf("%d",&T);while (T--){scanf("%d%d",&n,&m);if (n<=m)puts("first");//多余的一行 else puts((n%(m+1))?"first":"second");}return 0;
} 

hdu2147

#include
using namespace std;int main(){int n,m;while (scanf("%d%d",&n,&m)==2&&n&&m){puts((n&m&1)?"What a pity!":"Wonderful!");}return 0;
}

hdu2188

#include
using namespace std;
int main(){int T,n,m;scanf("%d",&T);while (T--){scanf("%d%d",&n,&m);puts((n%(m+1))?"Grass":"Rabbit");}return 0;
} 

hdu2148

PN似乎反过来了。。。。找规律

#include
using namespace std;
int main(){int n,m;while (scanf("%d%d",&m,&n)==2){if (n>=m){for (int i=m;iprintf("%d ",i);printf("%d
",n);}else {int x=m%(n+1);if (x)printf("%d
",x);else puts("none");}}return 0;
} 

Nim游戏

对于一个Nim游戏的局面(a1,a2,…,an),它是P-position当且仅当a1^a2^…^an=0,其中^表示异或(xor)运算。

先记个结论(坑以后再填)

hdu1907

#include
using namespace std;
int main(){int T,n,x;scanf("%d",&T);while (T--){scanf("%d",&n);int ans=0,cnt=0;for (int i=1;i<=n;i++){scanf("%d",&x);ans ^= x;if (x>1)cnt++;}if (!cnt)ans = !(n&1);if (ans)puts("John");else puts("Brother");}return 0;
} 

hdu2509

#include
#include
using namespace std; int main(){int n,x;while (scanf("%d",&n)==1){int ans=0,cnt=0;for (;n--;){scanf("%d",&x);ans ^= x;if (x>1) cnt++;}if (!cnt)ans = !!(n&1);//这个时候n都=0了,前面循环应该for个i,这里能过是因为数据弱吧 if (ans)puts("Yes");else puts("No");}return 0;
}

hdu1527

威佐夫博弈

#include
#include
#include
using namespace std;
const double phi=(1+sqrt(5))/2.0;
int main(){int m,n;while (scanf("%d%d",&n,&m)==2){if (min(n,m)==(int)(phi*abs(n-m)))puts("0");else puts("1");}return 0;
} 

继续练手

hdu1847

#include
using namespace std;
int main(){int n;while (scanf("%d",&n)==1){if (n%3==0)puts("Cici");else puts("Kiki");}return 0;
}

hdu1849

#include
using namespace std;
int main(){int n,x;while (scanf("%d",&n)==1&&n){int ans=0;for (;n--;){scanf("%d",&x);ans ^= x;}puts(ans?"Rabbit Win!":"Grass Win!");}return 0;
} 

hdu1850

#include
using namespace std;
const int N=111;
int a[N];
int main(){int n;while (~scanf("%d",&n)&&n){int nim=0;for (int i=1;i<=n;i++){scanf("%d",&a[i]);nim ^= a[i];}if (!nim)puts("0");else {int cnt=0;for (int i=1;i<=n;i++){int kk = nim^a[i];if (a[i]>kk)cnt++;}printf("%d
",cnt);}}return 0;
} 

SG函数模板

理论详细解释

这里写图片描述

hdu1848

#include
#include
using namespace std;
const int N = 1007;
int sg[N],fib[N];void getFib(){fib[1] = 1 , fib[2] = 2;for (int i=3;i<=17;i++)fib[i]=fib[i-1]+fib[i-2];
}void getSG(){getFib();/*memset(sg,0,sizeof(sg));int lastP;for (int i = 0; i < N ; i++ ){if (sg[i]==-1) sg[i] = i-lastP;else {//sg[i]==0lastP = i ;for (int j=1;j<17&&i+fib[j]int j;sg[0]=0;bool mex[17];for(int i=1;imemset(mex,0,sizeof(mex));for (j=1 ;fib[j]<=i ;j++ )mex[sg[i-fib[j]]]=1;for (j=0 ; jif(!mex[j])break;sg[i] = j;}}
//by cww97
int main(){int x,y,z;getSG();while (scanf("%d%d%d",&x,&y,&z)==3){if ( !x&& !y&& !z ) break;int ans = sg[x]^sg[y]^sg[z];if (ans)puts("Fibo");else puts("Nacci");}return 0;
} 

hdu1536

再次上演悲剧,调试N弄成了15,然后RTE,然后设成了10W(题目上数字看错了),然后TLE,然后,,,,好气啊

这里写图片描述

#include
#include
#include
using namespace std;
const int N=10007;
int s[110],sg[N],k;void getSG(){sg[0]=0;bool vis[N];for (int i=1;imemset(vis,0,sizeof(vis));for (int j=1;s[j]<=i&&j<=k;j++)vis[sg[i-s[j]]]=1;for (int j=0;jif(!vis[j]){sg[i]=j;break;}}
}int main(){//freopen("fuck.in","r",stdin);int m,n,x;while (scanf("%d",&k)==1&&k){for (int i=1;i<=k;i++)scanf("%d",&s[i]);sort(s+1,s+k+1);getSG();scanf("%d",&n);while (n--){scanf("%d",&m);int ans=0;while (m--){scanf("%d",&x);ans ^= sg[x];}putchar(ans?'W':'L');}puts("");}return 0;
} 

hdu5724

第一次多校训练的题,,就是这题引出了这一整篇文fei章hua

学(zhuang)术(bi)一点的说法是,状态压缩+SG

先说状态压缩

简单点的话,一行一行处理,第i个格子有棋子就 +1<< i(2的i次方) ,最后得到一个数字表示这一行的一种状态,个人习惯从1开始数,,,于是1<<0=1遍没有意义,导致我的表只有偶数(一半是空的,为了个人的强迫症强行多开了一倍空间,不过我喜欢,嘻嘻),所以所有状态的最小值是0(没有棋子),最大是(1<<21-2)(所有格子都有棋子,等比数列求个和就行)。

SG嘛,对棋盘的每个状态求sg值,注意所有棋子集中在右边的时候是没法走的(sg=0),所以从大到小求,,,状态变化,我一开始写的加减号,然后看有人用的位运算,以为自己错了,改成位运算的样子,A了之后又感觉自己想法不错,改回加减号,果然还是A了,,当然,感觉用位运算更易于理(zhuang)解(bi)一点,这里贴的代码就是位运算版本的辣(mdzz,一个符号讲这么多废话)

#include
#include
using namespace std;
const int N=(1<<21)+7;
int sg[N];
int c[23],C;//the position of chessesint next(int x){ //move the x-th chess for (int i=x;i<=C;i++){if (c[i+1]>c[i]+1)return 1<<(c[i]+1);}return 0;
}void getSG(){bool vis[107];// enough??for (int i=N-9;i>=0;i-=2){ //downtoC=0;           //get the stituationfor (int j=1;j<=20;j++)//num->arrayif (i&(1<1]=21;memset(vis,0,sizeof(vis));//sgsgsgfor (int j=1;j<=C;j++){int nxt=next(j);//move a chessif (nxt)vis[sg[i^(1<1;//- +}for (int j=0;j<107;j++)if(!vis[j]){sg[i]=j;break;}}
}int main(){//freopen("fuck.in","r",stdin);int T,n,m,x;getSG();scanf("%d",&T);while (T--){int ans = 0;scanf("%d",&n);for (;n--;){int che = 0;scanf("%d",&m);for (;m--;){scanf("%d",&x);che |= 1<//+=}ans ^= sg[che];}if (ans)puts("YES");else puts("NO");}return 0;
}

转载于:https://www.cnblogs.com/cww97/p/7533992.html

更多相关:

  •         Apache POI是一个开源的利用Java读写Excel,WORD等微软OLE2组件文档的项目。        我的需求是对Excel的数据进行导入或将数据以Excel的形式导出。先上简单的测试代码:package com.xing.studyTest.poi;import java.io.FileInputSt...

  • 要取得[a,b)的随机整数,使用(rand() % (b-a))+ a; 要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a; 要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1; 通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。 要取得a到b之间的...

  • 利用本征图像分解(Intrinsic Image Decomposition)算法,将图像分解为shading(illumination) image 和 reflectance(albedo) image,计算图像的reflectance image。 Reflectance Image 是指在变化的光照条件下能够维持不变的图像部分...

  • 题目:面试题39. 数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输出: 2 限制: 1 <= 数组长度 <= 50000 解题: cl...

  • 题目:二叉搜索树的后序遍历序列 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。 参考以下这颗二叉搜索树:      5     /    2   6   /  1   3示例 1: 输入: [1,6,3,2,5] 输出...