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 a row.
If the row contains all 1s, the player looses. Otherwise, the player can select any number of integers
(but at least 1 and each of them should be greater than 1) from that row and then divides each of
the selected integers with any divisor other than 1. For example, 6 can be divided by 2, 3 and 6, but
cannot be divided by 1, 4 and 5. The player who first makes the matrix all 1s wins. In other words, if
in his/her move, player gets the matrix with all 1s, then he/she looses. Given the matrix, your task is
to determine whether the first player wins or not. Assume that both of the players will play perfectly
to win.
Input
The first line has a positive integer T, T ≤ 50, denoting the number of test cases. This is followed by
each test case per line.
Each test case starts with a line containing 2 integers N and M representing the number of rows
and columns respectively. Both N and M are between 1 and 50 inclusive. Each of the next N line each
contains M integers. All these integers are between 2 and 10000 inclusive.
Output
For each test case, the output contains a line in the format ‘Case #x: M’, where x is the case number
(starting from 1) and M is ‘YES’ when the first player has a winning strategy and ‘NO’ otherwise.
Sample Input
5
2 2
2 3
2 3
2 2
4 9
8 5
3 3
2 3 5
3 9 2
8 8 3
3 3
3 4 5
4 5 6
5 6 7
2 3
4 5 6
7 8 9
Sample Output
Case #1: NO
Case #2: NO
Case #3: NO
Case #4: YES
Case #5: YES
题目大意:玩家轮流选择某一行,将至少一个或者多个数变为他的真因数,两玩家都采取最佳策略,求游戏结果。
当每一行的所有数都是1的时候,就没有任何数可以变成真因数了,这时轮到谁谁就输了。任何一个合数都可以由几个质因数相乘得到,一个数变成他的真因数的过程,相当于除去他的一个或多个质因数,例如12的质因数为2,2,3,当他变成其真因数6时,相当于除去了质因数2,此时6还有三个真因数,6变成3时相当于除去质因数2,3只能除去质因数3变成1,这就很像nim游戏中的拿火柴的样子,对于一个数,你把他变成他的真因数的过程就相当于从他的质因数里取走一个或者多个,这题便转化成了n行,每行一个火柴堆,每个火柴堆的数量是该行所有数字的质因数数量之和,然后用nim求解。
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
#include<vector>
#include<string>
#include<cmath>
#include<set>
#include<map>
#include<queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int mod = 1000000007;
const int maxm = 50000005;
const int maxn = 10005;
const int M = 25;
int n, m;
bool vis[maxn];
int line[55];
int zhi[maxn];
int tot;
void init(){
tot = 0;
for (int i = 2; i < maxn; i++){
if (!vis[i]){
zhi[tot++] = i;
for (int j = i * 2; j < maxn; j += i){
vis[j] = 1;
}
}
}
}
int main() {
init();
int t,x;
scanf("%d", &t);
for(int cas=1;cas<=t;cas++){
memset(line, 0, sizeof line);
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++){
for (int j = 0; j < m; j++){
scanf("%d", &x);
int cnt = 0;
while (x!=1&&cnt<tot&&zhi[cnt]<=x){
if (x%zhi[cnt] == 0){ x /= zhi[cnt]; line[i]++; }
else{ cnt++; }
}
}
}
int ans = 0;
for (int i = 0; i < n; i++){
ans ^= line[i];
}
printf("Case #%d: ", cas);
if (ans == 0){ printf("NO\n"); }
else{ printf("YES\n"); }
}
return 0;
}