ACdream 1112 Alice and Bob(素筛+博弈SG函数)

Alice and Bob

Time Limit:3000MS     Memory Limit:128000KB     64bit IO Format:%lld & %llu

Submit Status Practice ACdream 1112

Description

Here  is Alice and Bob again !

Alice and Bob are playing a game. There are several numbers.

First, Alice choose a number n.

Then he can replace n (n > 1) with one of its positive factor but not itself or he can replace n with a and b. Here a*b = n and a > 1 and b > 1.

For example, Alice can replace 6 with 2 or 3 or (2, 3).

But he can‘t replace 6 with 6 or (1, 6). But you can replace 6 with 1.

After Alice‘s turn, it’s Bob‘s turn. Alice and Bob take turns to do so. Who can’t do any replace lose the game.

Alice and Bob are both clever enough. Who is the winner?

Input

This problem contains multiple test cases. The first line contains one number n(1 ≤ n ≤ 100000).

The second line contains n numbers.

All the numbers are positive and less than of equal to 5000000.

Output

For each test case, if Alice can win, output “Alice”, otherwise output “Bob”.

Sample Input

2
2 2
3
2 2 4

Sample Output

Bob
Alice

题意:给定n堆石子,每次可以按照规则将该堆石子的个数分为两堆或者将该堆石子的个数减少,

   谁不能继续操作了谁就输。

题解:规则如下,若n=a*b且a>1,b>1,可以将石子分为a,b两堆;或者可以减少为a或b。

   比如n=6,可以分为(2,3),2,3这三种情况,但是不能分为(1,6),1,6这三种情况。

   和HDU3032是一个问题,就是一个取石子问题,这里的8=2*2*2就是那道题里的3,这里的

   6=2*3就是那道题里的2。如果对这道题理解感到困难可以先阅读我的上上篇博客:

   http://www.cnblogs.com/Ritchie/p/5627242.html

   也就是说这道题是对每个数的素因子个数进行操作,即素数可以看做是一个1。

   设一个数x=a1^r1*a2^r2*...*an^rn;设sum = r1+r2+...+rn.

   然后所有的情况就可以表示为:

   (1,sum-1),(2,sum-2),...(sum/2,sum-sum/2)或者(1),(2),...(n-1)

   然后在计算sum的时候我们可以这样计算。

   设一个数为x,他的最小的素因子为y.则sum[x] = sum[x/y] + 1;

   所以我们在素筛打表的时候要记录每个数的最小素因子以用于上述公式。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define maxn 5000050
int prime[maxn],cnt=0;
bool isprime[maxn];
int m[maxn];
int a[maxn];
int sg[105];
void getprime()
{
    memset(isprime,0,sizeof(isprime));
    memset(m,0,sizeof(m));
    memset(a,0,sizeof(a));
    for(int i=2; i<=maxn; i++)
    {
        if(!isprime[i])
        {
            prime[cnt++]=i;
            for(int j=i+i; j<=maxn; j+=i)
            {
                isprime[j]=1;
                if(!m[j]) m[j]=i;
            }
            m[i]=i;
        }
    }
    for(int i=2; i<=maxn; i++)
        a[i]=a[i/m[i]]+1;
}
void getsg()
{
    memset(sg,0,sizeof(sg));
    sg[0]=0;
    sg[1]=1;
    bool vis[105]; //放到循环里定义也一样需要每次都初始化
    for(int i=2; i<=100; i++)
    {
        memset(vis,0,sizeof(vis)); //注意每次都要初始化
        for(int j=0; j<i; j++) //取石子
            vis[sg[j]]=1;
        for(int j=1; j<i; j++) //拆分
            vis[sg[j]^sg[i-j]]=1;
        for(int x=0;; x++)
            if(!vis[x])
            {
                sg[i]=x;
                break;
            }
    }
}
void get()
{
    getsg();
    getprime();
}
void solve()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int data,ans=0;
        for(int i=0; i<n; i++)
        {
            scanf("%d",&data);
            ans^=sg[a[data]];
        }
        if(ans)
            printf("Alice\n");
        else
            printf("Bob\n");
    }
}
int main()
{
    get();
    solve();
}
时间: 2025-01-22 15:55:58

ACdream 1112 Alice and Bob(素筛+博弈SG函数)的相关文章

ACdream 1112 Alice and Bob (sg函数的变形+素数筛)

题意:有N个数,Alice 和 Bob 轮流对这些数进行操作,若一个数 n=a*b且a>1,b>1,可以将该数变成 a 和 b 两个数: 或者可以减少为a或b,Alice先,问谁能赢 思路:首先单看对每个数进行除法的操作,我们可以知道其实是在除以每个数的素因子或素因子之间的积 比如 70=2*5*7 我们可以变成 10(2*5)或 14(2*7) 或 35(5*7)或 2 或 5 或 7 或 1 这七种状态 当我们把他们(2,5,7)当作3个石子也就是一堆时,然而实际上我们是将这堆石子进行ni

Alice and Bob HDU - 4111 (SG函数)

Alice and Bob are very smart guys and they like to play all kinds of games in their spare time. The most amazing thing is that they always find the best strategy, and that's why they feel bored again and again. They just invented a new game, as they

ACdream 1112 Alice and Bob (博弈&amp;amp;&amp;amp;素数筛选优化)

题目链接:传送门 游戏规则: 没次能够将一堆分成两堆 x = a*b (a!=1&&b!=1)x为原来堆的个数,a,b为新堆的个数. 也能够将原来的堆的个数变成原来堆的约数y.y!=x.进行最后一次操作的人获胜. 分析: 也是一个去石头的游戏,因此我们仅仅须要将全部情况的sg值异或起来就好了. 我们首先来考虑一堆.设这一堆的个数为x: 那么全部的情况就是 (a1,x/a1), (a2,x/a2),...,(an,x/an);或者(a1),(a2),..,(an). 由于数据量比較大,我们朴

ACdream 1112 Alice and Bob (博弈&amp;&amp;素数筛选优化)

题目链接:传送门 游戏规则: 没次可以将一堆分成两堆 x = a*b (a!=1&&b!=1)x为原来堆的个数,a,b为新堆的个数. 也可以将原来的堆的个数变成原来堆的约数y,y!=x.进行最后一次操作的人获胜. 分析: 也是一个去石头的游戏,因此我们只需要将所有情况的sg值异或起来就好了. 我们首先来考虑一堆.设这一堆的个数为x: 那么所有的情况就是 (a1,x/a1), (a2,x/a2),...,(an,x/an);或者(a1),(a2),..,(an). 由于数据量比较大,我们朴素

hdu 3032(博弈sg函数)

题意:与原来基本的尼姆博弈不同的是,可以将一堆石子分成两堆石子也算一步操作,其它的都是一样的. 分析:由于石子的堆数和每一堆石子的数量都很大,所以肯定不能用搜索去求sg函数,现在我们只能通过找规律的办法求得sg的规律. 通过打表找规律可以得到如下规律:if(x%4==0) sg[x]=x-1; if(x%4==1||x%4==2) sg[x]=x; if(x%4==3) sg[x] = x+1. 打表代码: #include<iostream> #include<cstdio> #

UVA 10561 - Treblecross(博弈SG函数)

UVA 10561 - Treblecross 题目链接 题意:给定一个串,上面有'X'和'.',可以在'.'的位置放X,谁先放出3个'X'就赢了,求先手必胜的策略 思路:SG函数,每个串要是上面有一个X,周围的4个位置就是禁区了(放下去必败),所以可以以X分为几个子游戏去求SG函数的异或和进行判断,至于求策略,就是枚举每个位置就可以了 代码: #include <stdio.h> #include <string.h> #include <algorithm> usi

UVA 11534 - Say Goodbye to Tic-Tac-Toe(博弈sg函数)

UVA 11534 - Say Goodbye to Tic-Tac-Toe 题目链接 题意:给定一个序列,轮流放XO,要求不能有连续的XX或OO,最后一个放的人赢,问谁赢 思路:sg函数,每一段...看成一个子游戏,利用记忆化求sg值,记忆化的状态要记录下左边和右边是X还是O即可 代码: #include <stdio.h> #include <string.h> const int N = 105; int t, sg[3][3][N]; char str[N]; int ge

Light OJ 1296 - Again Stone Game (博弈sg函数递推)

F - Again Stone Game Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Description Alice and Bob are playing a stone game. Initially there are n piles of stones and each pile contains some stone. Alice stars the

Light OJ 1199 - Partitioning Game (博弈sg函数)

D - Partitioning Game Time Limit:4000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Description Alice and Bob are playing a strange game. The rules of the game are: Initially there are n piles. A pile is formed by some cell