制作企业网站宣传图步骤什么是嵌入式软件工程师
制作企业网站宣传图步骤,什么是嵌入式软件工程师,百度网站排名哪家好,品优购网页制作素材文章目录 前言一、Nim游戏1.题目描述输入格式输出格式数据范围输入样例#xff1a;输出样例#xff1a; 2.算法 二、台阶-Nim游戏1.题目描述输入格式输出格式数据范围输入样例#xff1a;输出样例#xff1a; 2.算法 三、集合-Nim游戏1.题目描述输入格式输出格式数据范围输… 文章目录 前言一、Nim游戏1.题目描述输入格式输出格式数据范围输入样例输出样例 2.算法 二、台阶-Nim游戏1.题目描述输入格式输出格式数据范围输入样例输出样例 2.算法 三、集合-Nim游戏1.题目描述输入格式输出格式数据范围输入样例输出样例 2.算法 四、拆分-Nim游戏1.题目描述输入格式输出格式数据范围输入样例输出样例 2.算法 前言 博弈论又被称为对策论(Game Theory)既是现代数学的一个新分支也是运筹学的一个重要学科。博弈论主要研究公式化了的激励结构间的相互作用是研究具有斗争或竞争性质现象的数学理论和方法。博弈论考虑游戏中的个体的预测行为和实际行为并研究它们的优化策略。 一、Nim游戏
1.题目描述
给定 n 堆石子两位玩家轮流操作每次操作可以从任意一堆石子中拿走任意数量的石子可以拿完但不能不拿最后无法进行操作的人视为失败。
问如果两人都采用最优策略先手是否必胜。
输入格式
第一行包含整数 n。
第二行包含 n 个数字其中第 i 个数字表示第 i 堆石子的数量。
输出格式
如果先手方必胜则输出 Yes。
否则输出 No。
数据范围
1≤n≤105, 1≤每堆石子数≤109
输入样例
2
2 3输出样例
Yes2.算法
算法结论全部项异或如果异或为0a1^a2……an 0则先手必败异或为1(a1^a2……an x)则先手必胜如何证明证明异或非0进行一步操作便可以使得异或为0x的二进制表示中最高一位在第k位则a1~an中必然有一个数ai的第k位是1从ai对拿去ai - (ai - x)后该堆为ai^x则此时所有堆异或等于0证明异或为0不论怎么操作都会让异或非0可以用反证法如果a1^a2…ai…an 0且a1^a2…ai拿去后…an 0则两式异或得ai^ai拿去后 0则拿去前后不变不符合逻辑最后还要知道全为0时异或这种情况必然是先手必败所有这场游戏两人都实现最优策略则异或为0a1^a2……an 0则先手必败异或为1(a1^a2……an x)则先手必胜
#include iostream
#include algorithmusing namespace std;const int N 100010;int main()
{int n;scanf(%d, n);int res 0;while (n -- ){int x;scanf(%d, x);res ^ x;}if (res) puts(Yes);else puts(No);return 0;
}二、台阶-Nim游戏
1.题目描述
现在有一个 n 级台阶的楼梯每级台阶上都有若干个石子其中第 i 级台阶上有 ai 个石子(i≥1)。
两位玩家轮流操作每次操作可以从任意一级台阶上拿若干个石子放到下一级台阶中不能不拿。
已经拿到地面上的石子不能再拿最后无法进行操作的人视为失败。
问如果两人都采用最优策略先手是否必胜。
输入格式
第一行包含整数 n。
第二行包含 n 个整数其中第 i 个整数表示第 i 级台阶上的石子数 ai。
输出格式
如果先手方必胜则输出 Yes。
否则输出 No。
数据范围
1≤n≤105, 1≤ai≤109
输入样例
3
2 1 3输出样例
Yes2.算法
本题思路和上一题基本一致但我们要分两种情况当对手拿偶数台阶时我们可以通过拿取对手从偶数台阶下方到奇数台阶的部分把它再从奇数台阶下放到下一级偶数台阶这样保证了奇数台阶始终不变当对手拿奇数台阶时情况和我们上一题一摸一样所以奇数台阶异或为0则先手必败异或为1则先手必胜
#include iostream
#include algorithmusing namespace std;const int N 100010;int main()
{int n;scanf(%d, n);int res 0;for (int i 1; i n; i ){int x;scanf(%d, x);if (i 1) res ^ x; //判断奇偶再异或奇项}if (res) puts(Yes);else puts(No);return 0;
}三、集合-Nim游戏
1.题目描述
给定 n 堆石子以及一个由 k 个不同正整数构成的数字集合 S。
现在有两位玩家轮流操作每次操作可以从任意一堆石子中拿取石子每次拿取的石子数量必须包含于集合 S最后无法进行操作的人视为失败。
问如果两人都采用最优策略先手是否必胜。
输入格式
第一行包含整数 k表示数字集合 S 中数字的个数。
第二行包含 k 个整数其中第 i 个整数表示数字集合 S 中的第 i 个数 si。
第三行包含整数 n。
第四行包含 n 个整数其中第 i 个整数表示第 i 堆石子的数量 hi。
输出格式
如果先手方必胜则输出 Yes。
否则输出 No。
数据范围
1≤n,k≤100, 1≤si,hi≤10000
输入样例
2
2 5
3
2 4 7输出样例
Yes2.算法
首先我们需要知道一些博弈论的基础知识 1.Mex运算 设S表示一个非负整数集合.定义mex(S)为求出不属于集合S的最小非负整数运算,即: mes(S)min{x}。例如:S{0,1,2,4},那么mes(S)3。 2.SG函数 在有向图游戏中,对于每个节点x,设从x出发共有k条有向边,分别到达节点y1,y2,····yk,定义SG(x)的后记节点y1,y2,····yk的SG函数值构成的集合在执行mex运算的结果,即SG(x)mex({SG(y1),SG(y2)····SG(yk)})特别地,整个有向图游戏G的SG函数值被定义为有向图游戏起点s的SG函数值,即 SG(G)SG(s)。 3.有向图游戏的和 设G1G2,····,Gm是m个有向图游戏.定义有向图游戏G,他的行动规则是任选某个有向图游戏Gi,并在Gi上行动一步.G被称为有向图游戏G1,G2,·····,Gm的和。有向图游戏的和的SG函数值等于它包含的各个子游戏SG函数的异或和,即:SG(G)SG(G1)xorSG(G2)xor···xor SG(Gm) 我们可以举一个例子设取石子的集合为{25}且仅有一堆石子石子数为10终点SG值为0 当仅有一堆石子是如果SG10 0则必胜等于0则必败。原因当SG不等于0时下一个连接点必有一个是0当SG等于0时下一个连接点都是非0。所以先手只要不是0就可以一直给后手0的情况最终达到终点0先手胜利。 当有n堆石子时把每一堆石子的SG取出来发现这就是Nim游戏思路便和第一道例题一摸一样因为也是全为0的时候先手必败 所以所有堆石子的SG异或值不等于0先手必胜等于0先手必败
#includeiostream
#includecstring
#includealgorithm
#includesetusing namespace std;const int N110,M10010;
int n,m;
int f[M],s[N];//s存储的是可供选择的集合,f存储的是所有可能出现过的情况的sg值//记忆化搜索
int sg(int x)
{if(f[x]!-1) return f[x]; //因为取石子数目的集合是已经确定了的,所以每个数的sg值也都是确定的,如果存储过了,直接返回即可setint S; //因为在函数内部定义,所以下一次递归中的S不与本次相同for(int i0;im;i){int sums[i];if(xsum) S.insert(sg(x-sum)); //先延伸到终点的sg值后,再从后往前排查出所有数的sg值}for(int i0;;i)//循环完之后可以进行选出最小的没有出现的自然数的操作if(!S.count(i))return f[x]i;
}int main()
{cinm;for(int i0;im;i)cins[i];cinn;memset(f,-1,sizeof(f));//初始化f均为-1,方便在sg函数中查看x是否被记录过int res0;for(int i0;in;i){int x;cinx;res^sg(x);//观察异或值的变化,基本原理与Nim游戏相同}if(res) printf(Yes);else printf(No);return 0;
}四、拆分-Nim游戏
1.题目描述
给定 n 堆石子两位玩家轮流操作每次操作可以取走其中的一堆石子然后放入两堆规模更小的石子新堆规模可以为 0且两个新堆的石子总数可以大于取走的那堆石子数最后无法进行操作的人视为失败。
问如果两人都采用最优策略先手是否必胜。
输入格式
第一行包含整数 n。
第二行包含 n 个整数其中第 i 个整数表示第 i 堆石子的数量 ai。
输出格式
如果先手方必胜则输出 Yes。
否则输出 No。
数据范围
1≤n,ai≤100
输入样例
2
2 3输出样例
Yes2.算法
相比于集合-Nim这里的每一堆可以变成小于原来那堆的任意大小的两堆即a[i]可以拆分成(b[i],b[j]),为了避免重复规定b[i]b[j],即a[i]b[i]b[j]相当于一个局面拆分成了两个局面由SG函数理论多个独立局面的SG值等于这些局面SG值的异或和。因此需要存储的状态就是sg(b[i])^sg(b[j])与集合-Nim的唯一区别 #include iostream
#include cstring
#include unordered_setusing namespace std;const int N 110;int n;
int f[N];int sg(int x)
{if(f[x] ! -1) return f[x];unordered_setint S;for(int i 0 ; i x ; i)for(int j 0 ; j i ; j)//规定j不大于i避免重复S.insert(sg(i) ^ sg(j));//相当于一个局面拆分成了两个局面由SG函数理论多个独立局面的SG值等于这些局面SG值的异或和for(int i 0 ; ; i)if(!S.count(i))return f[x] i;
}int main()
{memset(f , -1 , sizeof f);cin n;int res 0;while(n--){int x;cin x;res ^ sg(x);}if(res) puts(Yes);else puts(No);return 0;
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/89551.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!