ZOJ 3529 A Game Between Alice and Bob (分解质因数+Nim博弈+输出方案)
Alice and Bob play the following game. A series of numbers is written on the blackboard. Alice and Bob take turns choosing one of the numbers, and replace it with one of its positive factor but not itself. The one who makes the product of all numbers become 1 wins. You can assume Alice and Bob are intelligent enough and Alice take the first turn. The problem comes, who is the winner and which number is Alice's first choice if she wins?
Input
This problem contains multiple test cases. The first line of each case contains only one number N (1<= N <= 100000) representing there are N numbers on the blackboard. The second line contains N integer numbers specifying the N numbers written on the blackboard. All the numbers are positive and less than or equal to 5000000.
Output
Print exactly one line for each test case. The line begins with "Test #c: ", where c indicates the case number. Then print the name of the winner. If Alice wins, a number indicating her first choice is acquired, print its index after her name, separated by a space. If more than one number can be her first choice, make the index minimal.
Sample Input
4 5 7 9 12 4 41503 15991 72 16057
Sample Output
Test #1: Alice 1 Test #2: Bob
Author: ZHOU, Yuchen
Contest: ZOJ Monthly, September 2011
题目的意思就是Alice和Bob玩游戏,从N个数字中,每次每个人选一个数字然后把这个数字变成它的一个因子,最后使得所有乘积为1的那个人获胜。
这道题确实一开始看的时候不好下手,但是想到每个数可以替换成它的因子,那么一个数最多变换的次数就是它的质因子的个数,然后每个数就可以转换成质因子的乘积
每次变换成这个数的因子就相当于从这些质因子中除去某些质因子,这么处理一下之后,这道题不就成了一个Nim博弈了嘛= =
每个数相当于一堆石子,质因子的个数相当于是每一堆的石子的数量,把这个数除到1相当于把所有的石子拿走,就是一个裸Nim了
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<stdlib.h> #include<queue> #include<stack> #include<algorithm> #include<ctype.h> #define LL __int64 using namespace std; const int MAXN=100000+50; const int MAX=50000+50; const int INF=0x3f3f3f3f; const double EPS=1e-9; int dir4[][2]={{0,1},{1,0},{0,-1},{-1,0}}; int dir8[][2]={{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}}; int dir_8[][2]={{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1}}; int n,a[MAXN],prime[MAX],isprime[MAX]; void init()//筛选MAXN范围以内的素数 { int sum=0; for(int i=2;i<MAX;i++) { if(!isprime[i]) { prime[sum++]=i; for(int j=i;j<MAX;j+=i) isprime[j]=1; } } } int change(int num)//分解质因子 { int ans=0; for(int i=0;prime[i]*prime[i]<=num;i++) { if(num%prime[i]==0) { while(num%prime[i]==0) { num/=prime[i]; ans++; } } } if(num>1) ans++;//考虑到可能是大于MAX的质数 return ans; } int main() { init(); int cnt=0; while(scanf("%d",&n)!=EOF) { int sum=0,temp; for(int i=1;i<=n;i++) { scanf("%d",&temp); a[i]=change(temp); sum^=a[i]; } if(sum==0) printf("Test #%d: Bob\n",++cnt); else { printf("Test #%d: Alice ",++cnt); for(int i=1;i<=n;i++) if((sum^a[i])<a[i]) { printf("%d\n",i); break; } } } return 0; }