zoukankan      html  css  js  c++  java
  • 江南乐(bzoj 3576)

    Description

     小A是一个名副其实的狂热的回合制游戏玩家。在获得了许多回合制游戏的世界级奖项之后,小A有一天突然想起了他小时候在江南玩过的一个回合制游戏。    游戏的规则是这样的,首先给定一个数F,然后游戏系统会产生T组游戏。每一组游戏包含N堆石子,小A和他的对手轮流操作。每次操作时,操作者先选定一个不小于2的正整数M (M是操作者自行选定的,而且每次操作时可不一样),然后将任意一堆数量不小于F的石子分成M堆,并且满足这M堆石子中石子数最多的一堆至多比石子数最少的一堆多1(即分的尽量平均,事实上按照这样的分石子万法,选定M和一堆石子后,它分出来的状态是固定的)。当一个玩家不能操作的时候,也就是当每一堆石子的数量都严格小于F时,他就输掉。(补充:先手从N堆石子中选择一堆数量不小于F的石子分成M堆后,此时共有N+M-1)堆石子,接下来小A从这N+M-1堆石子中选择一堆数量不小于F的石子,依此类推。
        小A从小就是个有风度的男生,他邀请他的对手作为先手。小A现在想要知道,面对给定的一组游戏,而且他的对手也和他一样聪明绝顶的话,究竟谁能够获得胜利?

    Input

        输入第一行包含两个正整数T和F,分别表示游戏组数与给定的数。
        接下来T行,每行第一个数N表示该组游戏初始状态下有多少堆石子。之后N个正整数,表示这N堆石子分别有多少个。

    Output


        输出一行,包含T个用空格隔开的0或1的数,其中0代表此时小A(后手)会胜利,而1代表小A的对手(先手)会胜利。

    Sample Input

    4 3
    1 1
    1 2
    1 3
    1 5

    Sample Output

    0 0 1 1

    HINT

      对于100%的数据,T<100,N<100,F<100000,每堆石子数量<100000。

      以上所有数均为正整数。

    /*
        一眼可以看出能枚举分成几堆,然后随便搞一搞,但是这样O(n^2)很明显会超时。
        我们发现,(n / i)(商向下取整),至多有2*sqrt(n)个不同的结果,所以可以用除法分块做,注意相邻的两个的奇偶性不一样,都要考虑。
    */
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    #define N 100010
    int T,F,id,mex[N],sg[N];
    bool done[N];
    
    int dfs(int n){
        if(n<F) return 0;
        if(done[n]) return sg[n];
        done[n]=1;
        for(int i=2;i<=n;i=n/(n/i)+1)
            for(int j=i;j<=i+1&&j<=n;j++)
                dfs(n/j),dfs(n/j+1);
        id++;
        for(int i=2;i<=n;i=n/(n/i)+1)
            for(int j=i;j<=i+1&&j<=n;j++){
                int tmp=0;
                if((n%j)%2==1) tmp^=sg[n/j+1];
                if ((j-n%j)%2==1) tmp^=sg[n/j];
                mex[tmp]=id;
            }
        for(sg[n]=0;mex[sg[n]]==id;sg[n]++);
        return sg[n];
    }
    
    void work(){
        int t,xsum=0;
        scanf("%d",&t);
        while(t--){
            int x;
            scanf("%d",&x);
            xsum^=dfs(x);
        }
        printf("%d",xsum==0?0:1);
    }
    
    int main(){
        scanf("%d%d",&T,&F);
        while(T--){
            work();
            if(T) printf(" ");
        }
        return 0;
    }
     
  • 相关阅读:
    动态规划——Best Time to Buy and Sell Stock IV
    动态规划——Split Array Largest Sum
    动态规划——Burst Ballons
    动态规划——Best Time to Buy and Sell Stock III
    动态规划——Edit Distance
    动态规划——Longest Valid Parentheses
    动态规划——Valid Permutations for DI Sequence
    构建之法阅读笔记05
    构建之法阅读笔记04
    构建之法阅读笔记03
  • 原文地址:https://www.cnblogs.com/harden/p/6653822.html
Copyright © 2011-2022 走看看