题目描述
Alice and Bob are in their class doing drills on multiplication and division. They quickly get bored and instead decide to play a game they invented.
The game starts with a target integer N≥2, and an integer M = 1. Alice and Bob take alternate turns. At each turn, the player chooses a prime divisor p of N, and multiply M by p. If the player’s move makes the value of M equal to the target N, the player wins. If M > N, the game is a tie.
Assuming that both players play optimally, who (if any) is going to win?
输入
The first line of input contains T (1≤T≤10000), the number of cases to follow. Each of the next T lines describe a case. Each case is specified by N (2≤N≤231-1) followed by the name of the player making the first turn. The name is either Alice or Bob.
输出
For each case, print the name of the winner (Alice or Bob) assuming optimal play, or tie if there is no winner.
样例输入
10
10 Alice
20 Bob
30 Alice
40 Bob
50 Alice
60 Bob
70 Alice
80 Bob
90 Alice
100 Bob
样例输出
Bob
Bob
tie
tie
Alice
tie
tie
tie
tie
Alice
博弈论的问题,就是对于N来说,所有的质因数的乘积一定等于他本身,这道题的意思就变成了每个人取一个质因数谁先把所有的质因数取尽谁就赢。这里的质因数的数量是指总数,如18的质因数有2,3,3,有3个。如果其本身就是一个质因数,则其质因数的数量为1。答案很明显了,其个数为奇数,先手必胜,偶数,先手必败。但是有一个关键的问题,这个游戏的操作者可以使游戏成为平局状态,也就是可以使所得的M比N大,比如30,其质因数为2,3,5,无论先手取哪一个,后手只要和先手取一样的数,都可以使游戏成为平局状态,对于必败方而言,只要自己的可操作的总数比出现次数最少的那个质因数多的话,败方就可以把游戏状态从失败变成平局“tie”,但胜方不会这么做,所以这个处理一定是对败方才进行的,而且胜方为了阻止败方把游戏变成平局,一定会选取出现次数最多的那个质数,比如18,如果先手(胜方)选取2的话,后手再拿一个2就变成平局了,这不是胜方希望看到的。而对于先手操作状态即是初始状态,但后手操作状态一定是先手拿过一次后的状态。回到刚才所说的败方要把状态变成平局的问题,先手操作就是对初始状态操作即可,但后手就要对先手拿过一次后的状态进行处理,N的质因数为奇数时先手必胜,后手要把游戏变成平局,N为偶数时,先手要把游戏状态变成平局。双方的可操作数都是(质因数总数/2),只要比一下可操作数与质数最小的出现次数,谁更大,即可判断是否可能平局。
#include <bits/stdc++.h> #include <map> using namespace std; map <string,int> A; map<int,int> B; int prime[100005]; int s,num; void PrimeDecomposition(int k) { if(k<2) ; else if(k==2) { prime[s]=2; B[2]=1; num++; } else { for(int i=2; i<=sqrt(k); i++) { while(k>=i) { if(k%i==0) { num++; if(!B[i]) prime[s++]=i; B[i]++; k=k/i; } else break; } } if(k!=1) { if(!B[k]) { num++; prime[s++]=k; } B[k]++; } } } int main() { A["Alice"]=1; A["Bob"]=2; A["tie"]=3; int t,n; string tmp; cin>>t; while(t--) { cin>>n>>tmp; int mark=A[tmp]; memset(prime,0,sizeof(prime)); B.clear(); s=0; num=0; PrimeDecomposition(n); //cout<<num<<‘ ‘<<s<<endl; //for(int i=0; i<s; i++) //cout<<prime[i]<<‘ ‘<<B[prime[i]]<<endl; int mini=100005,ans,maxi=0,m; if(num%2==1){ for(int i=0;i<s;i++) { if(B[prime[i]]>maxi) { maxi=B[prime[i]]; m=prime[i]; } } B[m]--; } for(int i=0; i<s; i++) { if(B[prime[i]]<mini) mini=B[prime[i]]; } ans=num/2; //cout<<mini<<‘ ‘<<ans<<endl; if(mini<ans) { cout<<"tie"<<endl; continue; } if(num%2==0) { if(mark==1) { cout<<"Bob"<<endl; continue; } if(mark==2) { cout<<"Alice"<<endl; continue; } } if(num%2==1) { if(mark==2) { cout<<"Bob"<<endl; continue; } if(mark==1) { cout<<"Alice"<<endl; continue; } } } return 0; }
原文地址:https://www.cnblogs.com/shadowlink/p/8942901.html