zoukankan      html  css  js  c++  java
  • [hdu7022]Jsljgame

    先考虑$x=y$的情况,此时即是一个平等博弈,因此考虑$sg$函数

    具体的,有$sg(n)=egin{cases}0&(n=0)\mex({sg(n-i)mid 1le ile n,i e x})&(nge 1)end{cases}$,简单计算$sg(n)$的前几项,不难发现规律$sg(n)=lfloorfrac{n}{2x} floor x+n mod x$,进而将其异或即可

    (若异或和为0则先手必败,否则先手必胜)

    接下来,不妨假设$x>y$且$a_{1}le a_{2}le ...le a_{n}$,此时再分类讨论:

    1.若$a_{n}<y$,显然限制没有意义,仍是一个平等博弈,并且有$sg(n)=n$

    2.若$a_{n}ge y$,此时先手必胜,证明如下——

    对其进行归纳($n$和${a_{i}}$的字典序),并对此分类讨论:

    1.若$n=1$或$a_{n-1}<y$,则总存在$(i,z)$满足$1le ile n$且$0le z<a_{i}$,使得若$a_{i}=z$则$igoplus_{i=1}^{n}a_{i}=0$,那么再对$(i,z)$分类讨论——

    a.若$1le i<n$或$i=n$且$z e a_{n}-x$,那么将第$i$堆取到$z$个

    b.若$i=n$且$z=a_{n}-x$,那么将第$n$堆取到$z+y$个

    不论是哪一种情况,后手操作后若$a_{n}ge y$由归纳假设先手必胜,否则必然异或和非0(第一种情况异或和初始为0且必然变化,第二种情况只能在第$n$堆中取$y$个)同样先手必胜

    2.若$nge 2$且$a_{n-1}ge y$,再分类讨论:

    a.若$nge 3$或$a_{n}>y$,那么先手只需要在第$n-2$或第$n$堆中取一个,后手不可能同时使$a_{n-1},a_{n}<y$,那么由归纳假设先手必胜

    b.若$n=2$且$a_{n}=y(=a_{n-1})$,那么先手只需要取完第$n-1$堆,之后后手不能取完第$n$堆,后手操作后先手再取完第$n$堆即可

    类似地,对于$x<y$的情况,再分类讨论:

    1.若$a_{n}<x$,同样为$sg(n)=n$的平等博弈

    2.若$a_{n}ge x$,此时先手操作后必然要使$max_{i=1}^{n}a_{i}<x$(否则由之前的结论后手必胜),那么也即是要$n=1$或$a_{n-1}<x$,进而要保证异或和为0,即要求$S<x$且$S e a_{n}-x$(其中$S=igoplus_{i=1}^{n-1}a_{i}$)

    综上,时间复杂度为$o(nlog n)$(排序),可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 1005
     4 int t,n,x,y,ans,a[N];
     5 int main(){
     6     scanf("%d",&t);
     7     while (t--){
     8         scanf("%d%d%d",&n,&x,&y);
     9         for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    10         ans=0;
    11         if (x==y){
    12             for(int i=1;i<=n;i++)ans^=a[i]/(x<<1)*x+a[i]%x;
    13             if (ans)printf("Jslj
    ");
    14             else printf("yygqPenguin
    ");
    15             continue;
    16         }
    17         sort(a+1,a+n+1);
    18         if (a[n]<min(x,y)){
    19             for(int i=1;i<=n;i++)ans^=a[i];
    20             if (ans)printf("Jslj
    ");
    21             else printf("yygqPenguin
    ");
    22             continue;
    23         }
    24         if (x>y)printf("Jslj
    ");
    25         else{
    26             if ((n==1)||(a[n-1]<x)){
    27                 for(int i=1;i<n;i++)ans^=a[i];
    28                 if ((ans<x)&&(ans!=a[n]-x))printf("Jslj
    ");
    29                 else printf("yygqPenguin
    ");
    30             }
    31             else printf("yygqPenguin
    ");
    32         }
    33     }
    34     return 0;
    35 } 
    View Code
  • 相关阅读:
    腾讯会议API接入
    解决远程调用三方接口:javax.net.ssl.SSLHandshakeException报错
    iOS自动创建本地化文件
    数组转换
    2021MongoDB技术实践与应用案例征集活动获奖通知
    MongoDB按需物化视图介绍
    参会指南 | 2021MongoDB南京技术沙龙
    叮咚买菜自建MongoDB上云实践
    MongoDB技术实践与应用案例征集中
    使用WT工具恢复MongoDB数据
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15108956.html
Copyright © 2011-2022 走看看