链接
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2959
题解
把一个数变成它的真因子,其实就是除以一个它的约数(也就是除以若干素约数的乘积)
数变小之后,约数集合变动很大,但是素约数集合只减少了你除以的那些数
所以这题要从素约数集合入手
每一行,对于每个数字,如果它有
k
k
k个约数,那么就相当于有
k
−
1
k-1
k−1个石子,每次给它除以一个数就是拿走若干个石子,这一行的石子个数加起来看作一个石子堆
然后就是
n
i
m
nim
nim游戏了
代码
//NIM游戏
#include <bits/stdc++.h>
#define maxn 10010
using namespace std;
int N, M, a[maxn], prime[maxn], mark[maxn];
int read(int x=0)
{
int c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
return f*x;
}
void shai()
{
int i, j;
for(i=2;i<maxn;i++)
{
if(!mark[i])prime[++*prime]=i;
for(j=1;j<=*prime and i*prime[j]<maxn;j++)
{
mark[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
}
int main()
{
int i, j, T=read(), kase, nim_sum, k, x;
shai();
for(kase=1;kase<=T;kase++)
{
N=read(), M=read();
nim_sum=0;
for(i=1;i<=N;i++)
{
a[i]=0;
for(j=1;j<=M;j++)
{
x=read();
for(k=1;x>1;k++)while(x%prime[k]==0)x/=prime[k], a[i]++;
}
nim_sum^=a[i];
}
printf("Case #%d: ",kase);
if(nim_sum==0)printf("NO\n");
else printf("YES\n");
}
return 0;
}