石油大训练 Little Sub and Johann (博弈SG打表找规律)

Little Sub and Johann

题目描述

Little Sub and Johann are good friends and they often play games together. Recently, they like playing with stones.
They have n piles of stones initially and they should make one of following movements by turns:
1.Erase a pile of stones.
2.Suppose there is a stone pile which has x stones, you can erase y stones from it but the greatest common divisor of x and y should be 1.
If someone cannot make any legal movement, the other person win the game. We all know that Little Sub and Johann are very genius and will always follow the optimal strategy. If Little Sub take the first move, please tell us who will win the game eventually.

输入

There are multiple cases. the first line contains an integer T(1≤T≤100), indicating the number of cases.
There will be two line for each case. The fi rst line contains a integer n(1≤n≤100), indicating the number of stones piles.
The second line will be n integers Ai(1≤Ai≤106), indicating the number of stones in the ith pile.

输出

For each case please output exactly one line.
If Little Sub will win, please output ’Subconscious is our king!’. If Johann will win, please output ’Long live with King Johann!’

样例输入

复制样例数据

2
4
1 10 5 7
4
9 2 3 6

样例输出

Subconscious is our king!
Long live with King Johann!

题意:给你多堆石子,每次可以将其中一堆取完或者从该堆里面取走和该堆个数互质个数,问最后谁赢。题解:  一眼看出是裸的博弈SG,打了100的表,但是死活找不出规律,真是菜啊。%%%侯学长以下是学长思路:

    sg[0] = 0;

  sg[1] = mex{sg[0]} = 1;

  sg[2] = mex{sg[0],sg[1]} = 2;

  sg[3] = mex{sg[0],sg[1],sg[2]} = 3;

  sg[4] = mex{sg[0],sg[1],sg[3]} = 2;(缺少sg[2])

  sg[5] = mex{sg[0],sg[1],sg[2],sg[3],sg[4]} = 4;

  sg[6] = mex{sg[0],sg[1],sg[5]} = 2;(缺少sg[2],sg[3],sg[4])

  写到这里就可以发现当x为质数,sg[x] = k+1,k表示x是第k个质数。不然sg[x] = sg[y],y为x的最小质因子。

其实找规律不能硬找,需要先理解。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 using namespace std;
 6 const int maxn=1e6+10;
 7 int prime[maxn];
 8 int sg[maxn];
 9 int fac[maxn];
10 void get_prime()
11 {
12     for(int i=2;i<=maxn;i++)
13         if(prime[i]==0)
14         {
15             for(int j=i+i;j<=maxn;j+=i)
16             {
17                 prime[j]=1;
18                 if(!fac[j])
19                     fac[j]=i;
20             }
21         }
22 }
23
24 /*int gcd(int a,int b)
25 {
26     if(b==0)
27         return a;
28     return gcd(b,a%b);
29 }
30 void dfs(int t)
31 {
32     int vis[1100];
33     if(sg[t]!=-1)
34         return sg[t];
35     memset(vis,0,sizeof(vis));
36     for(int i=1;i<=t;i++)
37     {
38         if(gcd(i,t)==1||t==i)
39         {
40             vis[dfs(t-i)]=1;
41         }
42     }
43     for(int i=0;i<1100;i++)
44     {
45         if(vis[i]==0)
46             return sg[t]=i;
47     }
48 }*/
49 int main()
50 {
51     memset(sg,-1,sizeof(sg));
52 //    dfs(100);
53     get_prime();
54     sg[0]=0;
55     sg[1]=1;
56     int k=2;
57     for(int i=2;i<maxn;i++)
58     {
59         if(prime[i]==0)
60             sg[i]=k++;
61         else
62         {
63             if(i%2==0)
64                 sg[i]=2;
65             else
66                 sg[i]=sg[fac[i]];
67         }
68     }
69     int casen;
70     cin>>casen;
71     int n;
72     while(casen--)
73     {
74         int ans=0;
75         scanf("%d",&n);
76         for(int i=0;i<n;i++)
77         {
78             int x;
79             scanf("%d",&x);
80             ans^=sg[x];
81         }
82         if(ans!=0)
83         {
84             puts("Subconscious is our king!");
85         }
86         else
87         {
88             puts("Long live with King Johann!");
89         }
90     }
91
92
93 }

原文地址:https://www.cnblogs.com/1013star/p/10810114.html

时间: 2024-08-11 10:34:34

石油大训练 Little Sub and Johann (博弈SG打表找规律)的相关文章

HDU 3032 Nim or not Nim?(博弈 SG打表找规律)

传送门 Nim or not Nim? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1457    Accepted Submission(s): 720 Problem Description Nim is a two-player mathematic game of strategy in which players take

HDU2149-Good Luck in CET-4 Everybody!(博弈,打表找规律)

Good Luck in CET-4 Everybody! Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4762    Accepted Submission(s): 3058 Problem Description 大学英语四级考试就要来临了,你是不是在紧张的复习?或许紧张得连短学期的ACM都没工夫练习了,反正我知道的Kiki和C

[hdu-5795]A Simple Nim 博弈 尼姆博弈 SG函数打表找规律

[题目]题目链接 Two players take turns picking candies from n heaps,the player who picks the last one will win the game.On each turn they can pick any number of candies which come from the same heap(picking no candy is not allowed).To make the game more int

HDU 4203 博弈 打表找规律

http://acm.hdu.edu.cn/showproblem.php?pid=4203 一堆数量为s的硬币,两个人轮流从中取硬币,最后取完的人获胜,其中每次只能取k的n次方个硬币(n = 0, 1, 2, 3-),求想要取胜,当前要取走的最少硬币数. s的范围是1e9,直接储存sg函数是不现实的,所以考虑打表找找规律看. 通过打表可以得出规律: 当k为偶数时,sg函数值依次为 0 1 0 1 0 1 0 1- 当k为奇数时,sg函数值依次为 0 1 0 1 0 1-k(总长度为k + 1)

51nod_1714:B君的游戏(博弈 sg打表)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1714 nim游戏的一个变形,需要打出sg函数的表 #include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn=70000000; int sg[65], maxs; int vis[maxn]; //yu控制递归层数,cur控制所分配最大值,next控

hdu_5795_A Simple Nim(打表找规律的博弈)

题目链接:hdu_5795_A Simple Nim 题意: 有N堆石子,你可以取每堆的1-m个,也可以将这堆石子分成3堆,问你先手输还是赢 题解: 打表找规律可得: sg[0]=0 当x=8k+7时sg[x]=8k+8, 当x=8k+8时sg[x]=8k+7, 其余时候sg[x]=x:(k>=0) 1 #include<cstdio> 2 3 int main() 4 { 5 int t,n,ans,tp; 6 scanf("%d",&t); 7 while

EOJ——2019.9月赛 A 才艺展示 (博弈+打表找规律)

题目链接:https://acm.ecnu.edu.cn/contest/196/problem/A/ 题目:  解题报告: 由于必胜点是 n,所以 n 点的必胜状态为yes(走到这个点的人必胜),考虑 n-1 到 n/2+1 这一段(因为这一段都无法整除),所以 i 点的状态可以由i+1得到,接着从再从n/2推到1,由于有两种取法,所以对于当前状态 i,如果 i+1或者 2*i 的状态(这两点的状态前面已经推出来了),有一个为yes,那么这个 i 点的状态就为no(因为前面是由两者取最优的决策

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> #

51nod_1831: 小C的游戏(Bash博弈 找规律)

题目链接 此类博弈不需要考虑sg函数,只需要确定必胜态和必败态,解题思路一般为打败先打表找规律,而后找规律给出统一的公式.打表方式:给定初始条件(此题中为ok[0]=ok[1]=0),然后从低到高枚举某一状态的所有次态,若有存在必败次态,则当前状态为必胜态,否则当前状态必败. 题意:对单独一堆石子,支持两种操作:1.石子数-1:2.石子数变为原来石子数的某一因数.取走走后一堆或无法操作(面对n==0,坑啊..)者为负. 先打表找下规律 1 #include<bits/stdc++.h> 2 u