暑训令人绝望的第二个日子。。今天是博弈论入门

几个要点:

Nim-sum:Nim博弈中,状态(x1,x2...xn)为必败态当且仅当(x1,x2...xn)异或和为0

SG函数:定义SG(x)=mex(S),其中S是x所有后继状态的集合,mex(S)表示不在S中的最小非负整数

SG定理:组合游戏中,游戏和的SG函数等于各子游戏SG函数的Nim-sum

巴什博奕:有n个石子,两人轮流取,每人最多取m个。n%(m+1)=0时后手必胜,否则先手必胜

斐波那契博弈:有n个石子,两人轮流取,第一次可以取1~n-1个,以后每次最多取上次取数的两倍。当n为斐波那契数时是必败态

优质博客:

SG函数详解+例题  https://blog.csdn.net/strangedbly/article/details/51137432

题目:

A.

You and your friend are playing a game in which you and your friend take turns removing stones from piles. Initially there are N piles with a1, a2, a3, . . . , aN number of stones. On each turn, a player must remove at least one stone from one pile but no more than half of the number of stones in that pile. The player who cannot make any moves is considered lost. For example, if there are three piles with 5, 1 and 2 stones, then the player can take 1 or 2 stones from first pile, no stone from second pile, and only 1 stone from third pile. Note that the player cannot take any stones from the second pile as 1 is more than half of 1 (the size of that pile). Assume that you and your friend play optimally and you play first, determine whether you have a winning move. You are said to have a winning move if after making that move, you can eventually win no matter what your friend does.

Input

The first line of input contains an integer T (T ≤ 100) denoting the number of testcases. Each testcase begins with an integer N (1 ≤ N ≤ 100) the number of piles. The next line contains N integers a1, a2, a3, . . . , aN (1 ≤ ai ≤ 2 ∗ 1018) the number of stones in each pile.

Output

For each testcase, print ‘YES’ (without quote) if you have a winning move, or ‘NO’ (without quote) if you don’t have a winning move.

Sample Input

4

2

4 4

3

1 2 3

3

2 4 6

3

1 2 1

Sample Output

NO

YES

NO

YES

SG函数裸题,打表找规律,可以发现:当n能被2整除时,SG(n)=n/2,不能被整除时,SG(n)=SG(n/2)

#include <iostream>
typedef long long ll;
using namespace std;ll SG(ll n){if (n % 2 == 0) return n / 2;else return SG(n / 2);
}int main(){ll T, t, n, r;cin >> T;while (T--){cin >> n;r = 0;for (int i = 0; i < n; i++){cin >> t;r ^= SG(t);}if (r == 0) cout << "NO" << endl;else cout << "YES" << endl;}return 0;
}

B.

对于四川同胞遭受的灾难,全国人民纷纷伸出援助之手,几乎每个省市都派出了大量的救援人员,这其中包括抢险救灾的武警部队,治疗和防疫的医护人员,以及进行心理疏导的心理学专家。根据要求,我校也有一个奔赴灾区救灾的名额,由于广大师生报名踊跃,学校不得不进行选拔来决定最后的人选。经过多轮的考核,形势逐渐明朗,最后的名额将在“林队”和“徐队”之间产生。但是很巧合,2个人的简历几乎一模一样,这让主持选拔的8600很是为难。无奈,他决定通过捐款来决定两人谁能入选。 
选拔规则如下: 
1、最初的捐款箱是空的; 
2、两人轮流捐款,每次捐款额必须为正整数,并且每人每次捐款最多不超过m元(1<=m<=10)。 
3、最先使得总捐款额达到或者超过n元(0<n<10000)的一方为胜者,则其可以亲赴灾区服务。 
我们知道,两人都很想入选志愿者名单,并且都是非常聪明的人,假设林队先捐,请你判断谁能入选最后的名单? 

Input

输入数据首先包含一个正整数C,表示包含C组测试用例,然后是C行数据,每行包含两个正整数n,m,n和m的含义参见上面提到的规则。

Output

对于每组测试数据,如果林队能入选,请输出字符串"Grass", 如果徐队能入选,请输出字符串"Rabbit",每个实例的输出占一行。

Sample Input

2
8 10
11 10

Sample Output

Grass
Rabbit

巴什博奕裸题,思路如下:

1.当剩下的石子为m+1时,无论先手取多少个,后手都可以拿完剩下的,因此n=m+1是后手必胜态

2.所以,如果n能被m+1整除,只要每次先手取k个,后手取m+1-k个,就一定能达到n=m+1的状态,后手必胜

3.如果n不被m+1整除,只要先手取一个n%(m+1),即可使剩余石子数能被m+1整除,先手必胜

#include <iostream>
using namespace std;int main(){int t, n, m;cin >> t;while (t--){cin >> n >> m;if (n % (m + 1) == 0) cout << "Rabbit" << endl;else cout << "Grass" << endl;}return 0;
}

C.

虽然不想,但是现实总归是现实,Lele始终没有逃过退学的命运,因为他没有拿到奖学金。现在等待他的,就是像FarmJohn一样的农田生涯。

要种田得有田才行,Lele听说街上正在举行一场别开生面的拍卖会,拍卖的物品正好就是一块20亩的田地。于是,Lele带上他的全部积蓄,冲往拍卖会。

后来发现,整个拍卖会只有Lele和他的死对头Yueyue。

通过打听,Lele知道这场拍卖的规则是这样的:刚开始底价为0,两个人轮流开始加价,不过每次加价的幅度要在1~N之间,当价格大于或等于田地的成本价 M 时,主办方就把这块田地卖给这次叫价的人。

Lele和Yueyue虽然考试不行,但是对拍卖却十分精通,而且他们两个人都十分想得到这块田地。所以他们每次都是选对自己最有利的方式进行加价。

由于Lele字典序比Yueyue靠前,所以每次都是由Lele先开始加价,请问,第一次加价的时候, 
Lele要出多少才能保证自己买得到这块地呢?

Input

本题目包含多组测试,请处理到文件结束(EOF)。每组测试占一行。 
每组测试包含两个整数M和N(含义见题目描述,0<N,M<1100) 
Output

对于每组数据,在一行里按递增的顺序输出Lele第一次可以加的价。两个数据之间用空格隔开。
如果Lele在第一次无论如何出价都无法买到这块土地,就输出"none"。 
Sample Input

4 2
3 2
3 5

Sample Output

1
none
3 4 5

巴什博奕,保证留给对方的n可以被m+1整除即可
#include <iostream>
#include <vector>
using namespace std;vector<int> r;int main(){int n, m;while (cin >> m >> n){if (m % (n + 1) == 0) cout << "none" << endl;else{r.clear();for (int i = 1; i <= n; i++){if ((m - i) % (n + 1) == 0 || i > m) r.push_back(i);}for (int i = 0; i < r.size(); i++){if (i == r.size() - 1) cout << r[i] << endl;else cout << r[i] << ' ';}}}return 0;
}

E.

大学英语四级考试就要来临了,你是不是在紧张的复习?也许紧张得连短学期的ACM都没工夫练习了,反正我知道的Kiki和Cici都是如此。当然,作为在考场浸润了十几载的当代大学生,Kiki和Cici更懂得考前的放松,所谓“张弛有道”就是这个意思。这不,Kiki和Cici在每天晚上休息之前都要玩一会儿扑克牌以放松神经。 
“升级”?“双扣”?“红五”?还是“斗地主”? 
当然都不是!那多俗啊~ 
作为计算机学院的学生,Kiki和Cici打牌的时候可没忘记专业,她们打牌的规则是这样的: 
1、  总共n张牌; 
2、  双方轮流抓牌; 
3、  每人每次抓牌的个数只能是2的幂次(即:1,2,4,8,16…) 
4、  抓完牌,胜负结果也出来了:最后抓完牌的人为胜者; 
假设Kiki和Cici都是足够聪明(其实不用假设,哪有不聪明的学生~),并且每次都是Kiki先抓牌,请问谁能赢呢? 
当然,打牌无论谁赢都问题不大,重要的是马上到来的CET-4能有好的状态。

Good luck in CET-4 everybody!

Input

输入数据包含多个测试用例,每个测试用例占一行,包含一个整数n(1<=n<=1000)。

Output

如果Kiki能赢的话,请输出“Kiki”,否则请输出“Cici”,每个实例的输出占一行。 
Sample Input

1
3

Sample Output

Kiki
Cici
#include <iostream>
using namespace std;int main(){int n;while (cin >> n){if (n % 3 == 0) cout << "Cici" << endl;else cout << "Kiki" << endl;}return 0;
}

G.

1堆石子有n个,两人轮流取.先取者第1次可以取任意多个,但不能全部取完.以后每次取的石子数不能超过上次取子数的2倍。取完者胜.先取者负输出"Second win".先取者胜输出"First win". 

Input

输入有多组.每组第1行是2<=n<2^31. n=0退出. 
Output

先取者负输出"Second win". 先取者胜输出"First win". 参看Sample Output. 

Sample Input

2
13
10000
0

Sample Output

Second win
Second win
First win
斐波那契博弈,打表找规律可以发现必败态是斐波那契数,证明我等渣渣看不懂orz。。。。打表:输出n=2-99时的情况,状态[i][j]记录n=i且上次取j个时的输赢
#include <iostream>
#include <string.h>
#define NMAX 100
using namespace std;bool vis[NMAX][NMAX];//[i][j]n=i且上次取j个的输赢
bool r[NMAX];int main(){int n, i, j, k;for (i = 0; i < NMAX; i++){for (j = 0; j < NMAX; j++) vis[i][j] = 1;}for (i = 2; i < NMAX; i++){r[i] = 0;     //n=i时的输赢for (j = 1; j < i; j++){if (!vis[i-j][j]){r[i] = 1;break;}}     //更新[i][n](n<i/2)的状态for (j = 1; j*2 < i; j++){for (int k = 1; k <= j*2; k++){vis[i][j] = 0;if (!vis[i-k][k]){vis[i][j] = 1;break;}}}}for (i = 2; i < NMAX; i++) cout << i << ' ' << r[i] << endl;return 0;
}

解题:

#include <iostream>
#include <map>
typedef long long ll;
using namespace std;map<ll, bool> fab;void cal_fab(ll a, ll b){if (a + b > ((1 << 31) - 1)) return;fab[a + b] = true;cal_fab(b, a + b);
}int main(){ll n = 0;cal_fab(0, 1);while (cin >> n){if (n == 0) return 0;if (fab.count(n)) cout << "Second win" << endl;else cout << "First win" << endl;}
}

K.

一年在外 父母时刻牵挂 
春节回家 你能做几天好孩子吗 
寒假里尝试做做下面的事情吧

陪妈妈逛一次菜场 
悄悄给爸爸买个小礼物 
主动地 强烈地 要求洗一次碗 
某一天早起 给爸妈用心地做回早餐

如果愿意 你还可以和爸妈说 
咱们玩个小游戏吧 ACM课上学的呢~

下面是一个二人小游戏:桌子上有M堆扑克牌;每堆牌的数量分别为Ni(i=1…M);两人轮流进行;每走一步可以任意选择一堆并取走其中的任意张牌;桌子上的扑克全部取光,则游戏结束;最后一次取牌的人为胜者。 
现在我们不想研究到底先手为胜还是为负,我只想问大家: 
——“先手的人如果想赢,第一步有几种选择呢?”

Input

输入数据包含多个测试用例,每个测试用例占2行,首先一行包含一个整数M(1<M<=100),表示扑克牌的堆数,紧接着一行包含M个整数Ni(1<=Ni<=1000000,i=1…M),分别表示M堆扑克的数量。M为0则表示输入数据的结束。 
Output

如果先手的人能赢,请输出他第一步可行的方案数,否则请输出0,每个实例的输出占一行。 
Sample Input

3
5 7 9
0

Sample Output

1

Nim博弈,改变一张扑克牌的数字,使所有数字的异或和为0.由于仅存在 n xor n=0,所以改变后的扑克牌数量必须等于剩余数字的异或和,而扑克牌数量只可减少不可增加,统计ai > a1^a2...ai-1^ai+1...an-1^an的情况数即可
#include <iostream>
using namespace std;int main(){int n, i, j, t, c, num[101];while (cin >> n){if (n == 0) return 0;for (i = 0; i < n; i++) cin >> num[i];c = 0;for (i = 0; i < n; i++){t = 0;for (j = 0; j < n; j++){if (i == j) continue;t ^= num[j];}if (num[i] > t) c++;}cout << c << endl;}return 0;
}

滚蛋了,睡觉了,剩下题后面补

 

转载于:https://www.cnblogs.com/Shepard/p/9411151.html

暑期集训 Day2 简单博弈论相关推荐

  1. 数学建模暑期集训14:博弈论与纳什均衡

    前言 博弈论的内容在数学建模中比较少见,但2020年国赛B题确实考到了这一部分,因此掌握一些基本的原理方法还是有所必要.并且,博弈论本身和模糊综合评价类型比较类似,都是难度不高,不太依赖编程的方法,掌 ...

  2. 暑期集训5:并查集 线段树 练习题A:  HDU - 1232 ​​​​​​​

    2018学校暑期集训第五天--并查集 线段树 练习题A  --   HDU - 1232 畅通工程 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅 ...

  3. 暑期集训3:几何基础 练习题D:  HDU - 2036 ​​​​​​​

    2018学校暑期集训第三天--几何基础 练习题D  --    HDU - 2036 改革春风吹满地 " 改革春风吹满地,  不会AC没关系;  实在不行回老家,  还有一亩三分地.  谢谢 ...

  4. 题解报告(CDUT暑期集训——第三场)

    题解报告(CDUT暑期集训--第三场) A - Problem A. Ascending Rating HDU - 6319 思路:单调队列板子题?(但是弱的一批的我还是不会用(有空补上 用的滑动窗口 ...

  5. 第一次暑期集训之前期排位赛

    今天结束了一个星期以来第五场个人新生排位赛,暑期集训的第一阶段就这么结束了,对于这一星期以来所能有的最大的体会就是心酸,从未有过的心酸,面对那一道道题目时百思不得其的无助与苦恼,难的不会,简单的也不太 ...

  6. 暑期集训5:并查集 线段树 练习题G: HDU - 1754

    2018学校暑期集训第五天--并查集 线段树 练习题G  --   HDU - 1754 I Hate It 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.  这让 ...

  7. 暑期集训5:并查集 线段树 练习题F:  HDU - 1166 ​​​​​​​

    2018学校暑期集训第五天--并查集 线段树 练习题F  --   HDU - 1166 敌兵布阵 C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A ...

  8. 暑期集训5:并查集 线段树 练习题B: HDU - 1213 ​​​​​​​

    2018学校暑期集训第五天--并查集 线段树 练习题B  --   HDU - 1213 How Many Tables Today is Ignatius' birthday. He invites ...

  9. 暑期集训4:栈,树,优先队列 例 :  UVA - 514 ​​​​​​​​​​​​​​

    2018学校暑期集训第四天--栈,树,优先队列 例题  --   UVA - 514 Rails There is a famous railway station in PopPush City. ...

最新文章

  1. 如何使用Intel vtune profilier?
  2. 《数学之美》第17章 由电视剧《暗算》所想到的—谈谈密码学的数学原理
  3. 吴恩达:诸位CEO,我有一本「AI转型秘籍」传授给你
  4. China Linux Kernel-ppt
  5. Spring框架基础知识
  6. Linux关于文件的权限笔记
  7. 美国大学计算机专业排名2014,2014年美国大学本科计算机专业排名
  8. lbp特征提取算法 知乎_Hog,SIFT以及LBP这三种特征有什么不同?
  9. [doc文档]widows apache+myql+php
  10. mybatis注解开发_Spring Boot 中集成 MyBatis
  11. IT兄弟连 JavaWeb教程 Servlet线程安全问题
  12. Centos如何安装163yum源
  13. java web xml配置详解_Java Servlet web xml 配置详解
  14. 下行物理信道rs_LTE下行物理信道与物理信号
  15. 计算机操作系统面试题库和答案
  16. python+django大学教室自习室预约管理系统
  17. Excel VBA 金融建模 培训
  18. 简单计算一下,发现炒房一点不划算
  19. python图片合成视频
  20. 公共关系礼仪实务章节测试题——社会关系和公共关系(一)

热门文章

  1. 对比Hashtable、HashMap、TreeMap有什么不同(转)
  2. mysql 5.6.26 驱动_mysql版本引起的驱动问题
  3. 计算机用户改路径,如何更改win7 Users(用户文件夹)文件存放位置?
  4. 鸿蒙如何连接电视,鸿蒙系统首秀,在自家设备上和普通电视大不相同
  5. 排名算法(一)--PageRank
  6. 决策树(四)--随机森林与GBDT
  7. “21天好习惯”第一期-20
  8. 库存出现负数 mysql_前台支付商品成功后,sku表库存,购买数量会重复执行减操作好几次了,导致库存为负数...
  9. 如何分析一个“排序算法”?
  10. 一、Java语言基础(3)_流程语句——控制循环结构语句