【jzoj 4024】 【佛山市选2015】石子游戏 {筛素数+博弈论(NIM博弈/SG函数)}

文章目录

  • 题目
  • 解题思路
  • 代码


题目

Description
Alice 和 Bob 总喜欢聚在一起玩游戏(T_T),今天他(她)们玩的是一款新型的取石子游戏。游戏一开始有N堆石子,Alice 和 Bob 轮流取出石子。在每次操作中,游戏者必须选择其中的一堆石子,并作出下列的其中一种操作:
(1)移去整堆石子
(2)假设石子堆中有X颗石子,取出Y颗石子,其中1<=Y 【假的,是取与x 互质(小于等于x)的数】
游戏结束的条件是:取出最后一颗石子的人胜出。众所周知,Alice和Bob都是绝顶聪明的,假设他们在游戏中都采取最优的策略,问最后谁会胜出游戏呢?

Alice先取。

Input
第一行包含一个整数T,表示测试数据的组数。
接下来T组测试数据,在每组数据中,第一行包含一个整数N,表示有多少堆石子。第二行N个正整数,分别表示每堆有多少颗石子。

Output
每组测试数据输出一行,表示获胜者的名字(Alice 或者 Bob)。


解题思路

通常的 N i m Nim Nim游戏的定义是这样的:有若干堆石子,每堆石子的数量都是有限的,合法的移动是"选择一堆石子并拿走若干颗(不能不拿)",如果轮到某个人时所有的石子堆都已经被拿空了,则判负(因为他此刻没有任何合法的移动)。任何一个 I C G ICG ICG都可以通过把每个局面看成一个顶点,对每个局面和它的子局面连一条有向边来抽象成这个"有向图游戏"。下 面我们就在有向无环图的顶点上定义 S p r a g u e − G r u n d y Sprague-Grundy SpragueGrundy函数。首先定义 m e x ( m i n i m a l e x c l u d a n t ) mex(minimal excludant) mex(minimalexcludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。例如 m e x 0 , 1 , 2 , 4 = 3 、 m e x 1 , 3 , 5 = 0 、 m e x = 0 mex{0,1,2,4}=3、mex{1,3,5}=0、mex{}=0 mex0,1,2,4=3mex1,3,5=0mex=0。对于一个给定的有向无环图,定义关于图的每个顶点的 S p r a g u e − G r u n d y Sprague-Grundy SpragueGrundy函数 g g g如下:KaTeX parse error: Expected '}', got 'EOF' at end of input: …)=mex{ g(y) | y x x x的后继 }。

s g [ i ] sg[i] sg[i]表示取走 i i i个的 s g sg sg值,因为本题要求必须要是质数,所以取的i是最小质因数。


代码

#include
using namespace std; 
int t,n,g,sg[1000001],num;
int main()
{
	scanf("%d",&t);
	sg[1]=1; num=1;
    for (int i=2;i<=1000000;i++)
     {
     	if (!sg[i])
		 {
     		sg[i]=++num; 
     		for (int j=i;j<=1000000;j+=i)
     		 if (!sg[j]) sg[j]=num; 
		 }
	 }	
	while (t--)
	{
		int b=0; 
		scanf("%d",&n); 
		for (int i=1;i<=n;i++)
		 scanf("%d",&g),b^=sg[g];
		if (b!=0) printf("Alice\n"); else printf("Bob\n"); 
	}
}

你可能感兴趣的:(博弈论(NIM博弈/SG函数),博弈论(NIM博弈/SG函数))