UVA 11859 Division Game (Nim博弈)

题目:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=32746

题意:有一个n*m(1<=n,m<=50)矩阵,每个元素均为2~10000之间的正整数,两个游戏者轮流操作。每次可以选一行中的1个或者大于1的整数,把他们中的每个数都变成它的某个真因子,比如12可以边长1,2,3,4或者6,不能操作的输。

分析:考虑每个数包含的素因子个数(比如12=2*2*3包含3个素因子),则让一个数“变成它的素因子”等价于拿掉它的一个或者多个素因子。这样每一行对应一个正整数x(x表示可以拿的素因子总个数),可以拿某一行的任意多个因子。这就转化成基本的Nim博弈了。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 103;
int prime[maxn],nprime,cnt[maxn*maxn];
bool isprime[maxn];
void doprime()
{
	nprime=0;
	fill(isprime+2,isprime+maxn,true);
	for(int i=2;i<maxn;i++)
		if(isprime[i])
		{
			prime[nprime++]=i;
			for(int j=2*i;j<maxn;j+=i)
				isprime[j]=false;
		}
}
void work()
{
	doprime();
	memset(cnt,0,sizeof(cnt));
	for(int i=2;i<=10000;i++)
	{
		int temp=i;
		for(int j=0;j<nprime;j++)
		{
			if(temp%prime[j]==0)
			{
				cnt[i]=cnt[temp/prime[j]]+1;
				temp=1;
				break;
			}
		}
		if(temp>1)
			cnt[i]=1;
	}
}
int main()
{
	work();
	int ncase,n,m,i,j,ans,x;
	scanf("%d",&ncase);
	for(int T=1;T<=ncase;T++)
	{
		scanf("%d%d",&n,&m);
		ans=0;
		for(i=1;i<=n;i++)
		{
			int cal=0;
			for(j=1;j<=m;j++)
			{
				scanf("%d",&x);
				cal+=cnt[x];
			}
			ans^=cal;
		}
		printf("Case #%d: %s\n",T,(ans?"YES":"NO"));
	}
	return 0;
}
时间: 2024-10-10 00:09:18

UVA 11859 Division Game (Nim博弈)的相关文章

UVA 11859 Division Game[Nim游戏]

题意:给定一个N*M的矩阵,每次可以选择同一行中的若干个数,把它们变成它们的质因子.问说先手的可否获胜. 同一行相当于1堆,数量就是所有数的质因子个数之和 #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; const int N=55; inline int read

UVA - 11859 Division Game

Division game is a 2-player game.In this game, there is a matrix of positive integers with N rows and M columns.Players make their moves in turns. In each step, the current player selects arow. If the row contains all 1s, the player looses. Otherwise

UVA 1559 - Nim(博弈dp)

UVA 1559 - Nim 题目链接 题意:一开始有s个石子,2n个人轮流取石子,每个人有个最大能取数目,2n个人奇数一队,偶数一队,取到最后一个石子的队输,问谁赢 思路:记忆化搜索,每个人取的时候对应的后继状态如果有一个必败态,则该状态为必胜态,如果都是必胜态,则该状态为必败态 代码: #include <stdio.h> #include <string.h> int n, s, m[25], dp[25][10005]; int dfs(int now, int state

ACM学习历程—HDU 3915 Game(Nim博弈 &amp;&amp; xor高斯消元)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3915 题目大意是给了n个堆,然后去掉一些堆,使得先手变成必败局势. 首先这是个Nim博弈,必败局势是所有xor和为0. 那么自然变成了n个数里面取出一些数,使得xor和为0,求取法数. 首先由xor高斯消元得到一组向量基,但是这些向量基是无法表示0的. 所以要表示0,必须有若干0来表示,所以n-row就是消元结束后0的个数,那么2^(n-row)就是能组成0的种数. 对n==row特判一下. 代码:

Uva 10404-Bachet&#39;s Game(博弈)

题目链接:点击打开链接 在DP专题里刷到的,看着像博弈就水过去了.. 题意:n件物品,两个人轮流取,每次取的数量必须为一个集合s(集合里肯定含有1)里的一个数字,最后不能取者输(即取走最后一件物品者胜). 思路:递推.设 w[i] 为有i件物品时的状态,w[i]=1代表先手必胜,w[i]=0代表先手必败.可以知道w[1]=1,递推生成所有状态. 可以知道对于一个状态,如果他的后继存在必败状态,则该状态为必胜状态:如果该状态的所有后继都为必胜状态,那么该状态为必败状态. #include <alg

hdu 5011 (nim博弈模版)

//nim博弈 //有n堆石头,两人轮流每次从一堆中拿至少1,之多全部的石头,没有石头可拿为lose //判断先手是win还是lose # include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int main() { int n,i; __int64 a,sum; while(~scanf("%d",&n)) { sum=0; fo

HDU 1849 Rabbit and Grass(nim博弈)

题目地址:HDU 1849 初次接触nim博弈,感觉好神奇的说...居然可以跟异或运算扯上关系....给人类的智商跪了...作为地球人我感到很自豪.. 具体证明什么的看这篇博客被.传送门 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #inclu

HDU 1907 Nim博弈变形

1.HDU 1907 2.题意:n堆糖,两人轮流,每次从任意一堆中至少取一个,最后取光者输. 3.总结:有点变形的Nim,还是不太明白,盗用一下学长的分析吧 传送门 分析:经典的Nim博弈的一点变形.设糖果数为1的叫孤独堆,糖果数大于1的叫充裕堆,设状态S0:a1^a2^..an!=0&&充裕堆=0,则先手必败(奇数个为1的堆,先手必败).S1:充裕堆=1,则先手必胜(若剩下的n-1个孤独堆个数为奇数个,那么将那个充裕堆全部拿掉,否则将那个充裕堆拿得只剩一个,这样的话先手必胜).T0:a1

UVa 725 Division --- 简单枚举

题目链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=666 /* UVa 725 Division --- 简单枚举 */ #include <cstdio> #include <cstring> bool used[10]; /* 判断传进来的两个数是否满足条件 */ bool judge(int a, i