【博弈论】Multiplication Game
题目描述
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 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
题目大意:两人轮流用所给数的质因数相乘,先达到所给数的人胜利,可出现平局,即某人的决策只能处于必败态则通过操作使博弈编程平局(我不能赢也不让你赢)amazing
思路分析:根据唯一解定理,质因数是的数目可分为三种情况分析:质因数只有一种、有两种以及大于三种。
(1)质因数只有一种:该质因数需要奇数个则先手获胜,若需要偶数个则后手获胜;
(2)质因数有两种:两种质因数所需数目相同,则后手获胜(不论先手如何操作,后手只需平衡即可);
两种质因数所需数目不同,if差值为一,则先手获胜;else原必败态可以通过操作使之平局;
(3)质因数有三种及三种以上:必然可以通过操作使之达到平局。
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 const int mod = 1e9+7; 5 typedef long long ll; 6 #define LL long long 7 8 const int maxn = 1e5+100; 9 10 int prime[maxn+1]; 11 12 bool vis[maxn]; 13 ll cnt; 14 void primejudge(int n) 15 { 16 cnt=0; 17 vis[1]=true; 18 ll i,j; 19 for(i=2; i<=n; i++) 20 { 21 if(!vis[i]) 22 { 23 prime[cnt++]=i; 24 } 25 for(j=0; j<cnt&&i*prime[j]<=n; j++) 26 { 27 vis[i*prime[j]]=true; 28 if(i%prime[j]==0) 29 { 30 break; 31 } 32 } 33 } 34 } 35 36 int main() 37 { 38 primejudge(maxn); 39 int T; 40 cin>>T; 41 while(T--) 42 { 43 ll n; 44 string ss; 45 cin>>n>>ss; 46 47 int ret = 0; 48 vector<int>v; 49 for(int i=0; i<cnt; i++) 50 { 51 52 if(n%prime[i]==0) 53 { 54 ret++; 55 int tmp=0; 56 while(n%prime[i]==0) 57 { 58 n/=prime[i]; 59 tmp++; 60 } 61 v.push_back(tmp); 62 } 63 if(ret>=3) 64 break; 65 } 66 if(n>1) 67 { 68 ret++; 69 v.push_back(1); 70 } 71 if(ret>=3) 72 { 73 cout<<"tie"<<endl; 74 } 75 else if(ret==1) 76 { 77 78 if(v[0]%2==0) 79 { 80 if(ss=="Alice") 81 cout<<"Bob"<<endl; 82 else 83 cout<<"Alice"<<endl; 84 } 85 else 86 { 87 if(ss!="Alice") 88 cout<<"Bob"<<endl; 89 else 90 cout<<"Alice"<<endl; 91 } 92 } 93 else if(ret==2) 94 { 95 96 //cout<<" 2 "<<endl; 97 if(v[1]==v[0]) 98 { 99 if(ss=="Alice") 100 cout<<"Bob"<<endl; 101 else 102 cout<<"Alice"<<endl; 103 } 104 else 105 { 106 if(abs(v[0]-v[1])==1) 107 if(ss!="Alice") 108 cout<<"Bob"<<endl; 109 else 110 cout<<"Alice"<<endl; 111 else 112 { 113 cout<<"tie"<<endl; 114 } 115 } 116 } 117 else 118 { 119 cout<<ss<<endl; 120 } 121 } 122 123 }
注意:这题开始队友wa了几发,一是数据是1e9的线性筛也无法预处理所有质因数,但是可以考虑只预处理1e5内的质数,因为大于1e5之后最多有且只有一个质因数,否则为它本身;
但在统计质因数时,仍需考虑一种特例,举例说明吧:若说给数为10000019,该数为质数但大于1e5,可直接ret++,但2*10000019,在统计质因数时要先统计2这个因子,然后因为商不等于一,ret++,同时v.push_back(1)。为什么要push呢,因为要比较质因数的出现次数啊,因为这个数大于1e5,所以它之后出现一次,故push_back(1)。