zoukankan      html  css  js  c++  java
  • [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	SG=%d
    ",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
  • 相关阅读:
    我的第一次面试 —— 腾讯 AI安全 一面总结
    从零开始openGL——五、光线追踪
    从零开始openGL——四、纹理贴图与n次B样条曲线
    从零开始openGL——三、模型加载及鼠标交互实现
    从零开始openGL—— 二、 基本图形绘制
    NN入门,手把手教你用Numpy手撕NN(三)
    2020计算机保研经验分享
    TCP实战二(半连接队列、全连接队列)
    TCP实战一(三握四挥、流量控制)
    tcpdump抓包工具的基本使用
  • 原文地址:https://www.cnblogs.com/lllxq/p/10808698.html
Copyright © 2011-2022 走看看