[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!

https://blog.csdn.net/qq_39239844/article/details/81100916

整个有向图游戏G的SG函数值被定义为有向图游戏起点的SG函数值;
有向图游戏的和的SG函数值等于它包含的各个子游戏SG函数值的异或值;

求出各堆石子的SG函数值,求异或和。

SG函数值暴力打表,发现规律:
若i为质数,SG[i]=它在质数表中的位置+1
若i为合数,SG[i]=SG[i的最小质因子]
/*打表*/
#include <bits/stdc++.h>
using namespace std;

int SG[1005],f[1005],N;
bool vis[1005];

void get_f(int x){
  N=0;
  for(int i=1;i<=x-1;i++){
    if(__gcd(i,x)==1) f[++N]=i;
  }
  f[++N]=x;
}

void get_SG(int n){
  SG[0]=0;
  for(int i=1;i<=n;i++){
    get_f(i);
    memset(vis,0,sizeof(vis));
    for(int j=1;j<=N&&f[j]<=i;j++){
        vis[SG[i-f[j]]]=1;
    }
    for(int j=0;;j++){
        if(!vis[j]){
            SG[i]=j;
            break;
        }
    }
  }
  for(int i=0;i<=n;i++){
    printf("i=%d\tSG=%d\n",i,SG[i]);
  }
}

int main()
{
    get_SG(100);
}
View Code
素数筛时预处理SG值
#include<bits/stdc++.h>
using namespace std;

int SG[1000010];
int cnt=0,prime[1000010];
bool vis[1000010];

void init(int n){
  vis[1]=1;
  SG[1]=1;
  for(int i=2;i<=n;i++){
    if(!vis[i]){
        prime[++cnt]=i;
        SG[i]=cnt+1;
    }
    for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
        vis[i*prime[j]]=1;
        SG[i*prime[j]]=SG[prime[j]];
        if(i%prime[j]==0) break;
    }
  }
}

int main()
{
    init(1000000);
    int t;scanf("%d",&t);
    while(t--){
        int n;scanf("%d",&n);
        int ans=0;
        for(int i=1;i<=n;i++){
            int x;scanf("%d",&x);
            ans^=SG[x];
        }
        if(ans) puts("Subconscious is our king!");
        else puts("Long live with King Johann!");
    }
    return 0;
}
View Code

 

posted @ 2019-05-04 15:49  l..q  阅读(308)  评论(0编辑  收藏  举报