HDU 6892 Lunch
原题传送门:Lunch
参考:2020ccpc网络赛
Problem Description
Now it's time for lunch. Today's menu is chocolate!
Though every baby likes chocolate, the appetites of babies are little. After lunch, there are still n pieces of chocolate remained: The length of the ith piece is \(li\).
Using the remained chocolate, Baby Volcano is going to play a game with his teacher, Mr. Sprague. The rule of the game is quite simple.
Two player plays in turns, and Baby Volcano will play first:
- In each turn, the player needs to select one piece of chocolate. If the length of the selected piece is equal to 1, the player of this turn will lose immediately.
- Suppose the length of the selected piece is l. Then the player needs to select a positive integer k satisfying k is at least 2 and k is a factor of l.
- Then the player needs to cut the selected piece into k pieces with length lk.
The game continues until one player selects a piece of chocolate with length 1.
Suppose both players plays optimally, your task is to determine whether Baby Volcano will win.
Input
The first line contains single integer \(t\)\((1≤t≤2∗10^4)\), the number of testcases.
For each testcase, the first line contains a single integer \(n\)\((1≤n≤10)\).
The second line contains n positive integers \(li(1≤li≤10^9)\), representing the length of each piece.
Output
For each testcase, output char 'W' if Baby Volcano will win, otherwise output char 'L'.
Sample Input
3
2
4 9
2
2 3
3
3 9 27
Sample Output
W
L
L
题意:有\(n\)个数,两人轮流进行操作,每次操作能将其中一个数\(x\)变为\(k*(x/k)\),此处的k必须是x的因子且\(k != x, k >= 2\)。当场上的数均为1时游戏结束,当前操作方输。问先手可不可以获胜。
思路:首先假设每一个数只能操作一次,那么我们考虑目前一共可以操作几次,假如面对只能剩下偶数次的操作次数那么必然面临必输结局,所以可以消耗一次操作来分开一个数以此来让对手面对必输结局,那么我们就只能将一个数分成奇数堆。那么这个数的质因子个数是这个数的最极限操作次数。而2是最特殊的质因子,因为2无论有多少个都相当于只能取一次。那么由上面的分析我们已经可以把这个问题可以简化成Nim游戏的模型了,质因子的个数即石子的个数,取多个石子即相当于分成几个质因子乘积堆。
#include <iostream>
using namespace std;
const int N = 1e7 + 10;
int primes[N], cnt;
bool st[N];
void init(int n){
for(int i = 2; i <= n; i++){
if(!st[i])primes[cnt++] = i;
for(int j = 0; primes[j] <= n / i; j++){
st[primes[j] * i] = true;
if(i % primes[j] == 0)break;
}
}
}
int calc(int n){
int ans = 0;
while(!(n & 1))n >>= 1, ans = 1;
for(int i = 0; primes[i] <= n / primes[i]; i++)
while(n % primes[i] == 0)
{
n /= primes[i];
ans++;
}
if(n != 1)ans++;
return ans;
}
int main(){
int t;
init(1e6);
scanf("%d", &t);
while(t--){
int n, m, ans = 0;
scanf("%d", &n);
while(n--){
scanf("%d", &m);
ans ^= calc(m);
}
if(ans)puts("W");
else puts("L");
}
return 0;
}

浙公网安备 33010602011771号