[JZOJ4024] 石子游戏

Description

  Alice 和 Bob 总喜欢聚在一起玩游戏(T_T),今天他(她)们玩的是一款新型的取石子游戏。游戏一开始有N堆石子,Alice 和 Bob 轮流取出石子。在每次操作中,游戏者必须选择其中的一堆石子,并作出下列的其中一种操作:
  (1)移去整堆石子
  (2)假设石子堆中有X颗石子,取出Y颗石子,其中1<=Y    
  游戏结束的条件是:取出最后一颗石子的人胜出。众所周知,Alice和Bob都是绝顶聪明的,假设他们在游戏中都采取最优的策略,问最后谁会胜出游戏呢?

  Alice先取。

Input

  第一行包含一个整数T,表示测试数据的组数。
  接下来T组测试数据,在每组数据中,第一行包含一个整数N,表示有多少堆石子。第二行N个正整数,分别表示每堆有多少颗石子。

Input

  第一行包含一个整数T,表示测试数据的组数。
  接下来T组测试数据,在每组数据中,第一行包含一个整数N,表示有多少堆石子。第二行N个正整数,分别表示每堆有多少颗石子。

Sample Input

  3
  3
  3 5 6
  4
  2 3 6 9
  5
  3 2 1 1000000 999999

Sample Output

  Alice
  Bob
  Alice

Data Constraint

  20%的数据,N<=5,每堆石子数量少于10
  100%的数据,T<=100,N<=100,每堆石子数量不大于1,000,000

Summary

  题目还有个条件是取第k堆石头j个,j与第k堆石头数互质。

  然后构造SG函数。

  若石头数是质数,那么对于小于 i 的所有正整数都可以被取到,那么 SGi则是它在质数表的排名+1。 

  若石头数是一个合数,那么 i 肯定存在某个因子为前面出现过的质数,那么 SGi 就应为最小质因子的 SG 值了。

  最后如果所有的SG值xor后为0,后手必胜,否则先手必胜。

Code

 1 #include<cstdio>
 2 using namespace std;
 3 int n,m,i,j,z[500000],sg[1000000];
 4 bool a[1000000];
 5 int main()
 6 {
 7     scanf("%d",&n);
 8     a[1]=true;
 9     int ma=1000000;    
10     for (int i=2;i<=1000;i++)
11         for (int j=2;j<=ma/i;j++)
12             a[i*j]=true;
13     int sum=0;
14     sg[1]=1;
15     for (int i=1;i<=ma;i++)
16         if (not a[i]) 
17         {
18             sum++;
19             z[sum]=i;
20             sg[i]=sum+1;
21         }
22         else
23         for (int j=1;j<=sum;j++)
24             if (i%z[j]==0)
25             {
26                 sg[i]=sg[z[j]];
27                 break;
28             }
29     for (int i=1;i<=n;i++)
30     {
31         scanf("%d",&m);
32         int ans=0;
33         for (int j=1;j<=m;j++)
34         {
35             int x;
36             scanf("%d",&x);
37             ans=ans^sg[x];
38         }
39         if (ans==0) printf("Bob\n");
40         else printf("Alice\n");
41     }
42 }
View Code

 

posted @ 2018-07-16 10:11  kasiruto  阅读(568)  评论(0编辑  收藏  举报