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:

  1. 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.
  2. 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.
  3. 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;
    
}
posted @ 2021-09-08 20:37  JOKE_MAKE  阅读(94)  评论(0)    收藏  举报