HDU 6892 Lunch (Nim博弈)

题目

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∗104), 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≤109), 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

思路

首先,我们发现题目时间给了三秒,然后我们发现所有数都是质数的情况下,比赛的胜负就十分特殊了,它由数的奇偶性决定,所以我们猜想这题的做法大概率是要去做素数筛法的。所以特殊的当这个数为2的次方的时候,就形成了一种平衡局面,先手必胜,可操作次数就相当于是奇数质因子之和加上是否为偶数,然后做nim和就可以了。

代码实现

      #include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define MT(x,i) memset(x,i,sizeof(x) )
#define rev(i,start,end) for (int i=start;i<end;i++)
#define inf 0x3f3f3f3f
#define mp(x,y) make_pair(x,y)
#define lowbit(x) (x&-x)
#define MOD 1000000007
#define exp 1e-8
#define N 1000005 
#define fi first 
#define se second
#define pb push_back
typedef long long ll;
const ll INF=0x3f3f3f3f3f3f3f3f;
typedef vector <int> VI;
typedef pair<int ,int> PII;
typedef pair<int ,PII> PIII;
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
void check_max (int &a,int b) { a=max (a,b);}
void check_min (int &a,int b) { a=min (a,b);}
inline int read() {
    char ch=getchar(); int x=0, f=1;
    while(ch<'0'||ch>'9') {
        if(ch=='-') f=-1;
        ch=getchar();
    } while('0'<=ch&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    } return x*f;
}

const int maxn=sqrt (1e9)+5;
int mark[maxn],pri[maxn];
int t,ans,cnt=0;

int F (int x) {
    if (x==1) return 0;
    int c=x%2==0;
    while (x%2==0) x/=2;
    int g=sqrt (x);
    for (int i=1;pri[i]<=g;i++) {
        if (x%pri[i]==0) {
            c++;
            while ((x/=pri[i])%pri[i]==0) c++;
            g=sqrt (x);
        }
    }
    return (x>1)+c;
}

int main () {

    rev (i,2,maxn) if (!mark[i]) {
        pri[++cnt]=i;
        for (int j=i+i;j<maxn;j+=i) mark[j]=1;
    }
    pri[++cnt]=1e6;
    int t;
    scanf ("%d",&t);
    while (t--) {
        int n,ans=0;
        scanf ("%d",&n);
        rep (i,1,n) {
            int x;
            scanf ("%d",&x);
            ans^=F (x);
        }
        if (ans==0) printf ("L
");
        else printf ("W
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/hhlya/p/13728320.html