题目: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