zoukankan      html  css  js  c++  java
  • TJUOJ4172解题报告【sg函数】

    题目地址:

      http://acm.tju.edu.cn/toj/showp4172.html

    题目概述:

      有一个长度为n的0/1序列,每次操作可以将两个连续的1变成0,问先手是否必胜。

    大致思路:

      博弈论还是很容易看出来的,不过比赛的时候忘了sg函数的定义导致这题一直WA,要吸取教训啊,对于这些学过的东西要经常复习复习。

      sg函数的定义是:sg(x)=mex{sg(y) | y是x的后继 }。mex表示最小的不属于这个集合的非负整数。

      辣么我们设sg(i)为一段全为1且长度是i的序列的sg值,则i的后继应该是sg(j) xor sg(i-j-2) ,j从0到i-2

      数据比较小,预处理一下所有长度的sg值就好了。

    复杂度分析:

      sg值的计算是O(n²)的,每次询问是O(n),总结起来就是O(n²)。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <vector>
    #include <ctime>
    #include <map>
    #include <assert.h>
    #include <stack>
    #include <set>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    #define sacnf scanf
    #define scnaf scanf
    #define maxn 1010
    #define maxm 20010
    #define inf 1061109567
    #define INF 0x3f3f3f3f
    #define Eps 0.000001
    const double PI=acos(-1.0);
    #define mod 1000000007
    #define MAXNUM 10000
    #define For(i,j,k) for(int (i)=(j);(i)<=(k);(i)++)
    #define mes(a,b) memset((a),(b),sizeof(a))
    typedef long long ll;
    typedef unsigned long long ulld;
    void Swap(int &a,int &b) {int t=a;a=b;b=t;}
    ll Abs(ll x) {return (x<0)?-x:x;}
    
    int sg[maxn],num[maxn];
    
    int main()
    {
        //freopen("data.in","r",stdin);
        //freopen("data.out","w",stdout);
        //clock_t st=clock();
        int n=1000;
        sg[0]=sg[1]=0;
        for(int i=2;i<=n;i++)
        {
            for(int j=0;j<=i;j++) num[j]=0;
            for(int j=0;j+2<=i;j++) num[sg[j]^sg[i-2-j]]=1;
            for(int j=0;;j++)
                if(!num[j]) {sg[i]=j;break;}
        }
        //for(int i=0;i<=n;i++) if(!sg[i]) cout<<i<<" ";
        int T;scanf("%d",&T);
        while(T--)
        {
            int n,x;scanf("%d",&n);
            int len=0,ans=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%1d",&x);
                if(x==1) len++;
                else
                {
                    if(len!=0) ans^=sg[len];len=0;
                }
            }
            if(len!=0) ans^=sg[len];
            printf(ans!=0?"Alice
    ":"Bob
    ");
        }
        //clock_t ed=clock();
        //printf("
    
    Time Used : %.5lf Ms.
    ",(double)(ed-st)/CLOCKS_PER_SEC);
        return 0;
    }
  • 相关阅读:
    从一个表格文件中录入信息,进行计算后,在文件中输出这个表格
    求一个字符串的最小正周期
    算法竞赛入门例题3-5生成元
    算法竞赛入门经典 例题3-4 猜数字游戏的提示
    回文词
    WERTYU找不出不能输出空格的原因SSSSSSSSSSSSS
    DAY 106 ES介绍
    DAY 105 redis集群搭建
    DAY 104 redis高级02
    DAY 103 redis高级01
  • 原文地址:https://www.cnblogs.com/CtrlKismet/p/7156709.html
Copyright © 2011-2022 走看看