首页 > 其他分享 >题解

题解

时间:2023-09-24 14:44:07浏览次数:53  
标签:Muri int 题解 pos 必胜 Yuri SG

题目大意

有 \(n\) 个杯子,第 \(i\) 个杯子里装有 \(W_i\) 升水,且有 \(n\) 对正整数 \(l_i,r_i\)。Yuri 和 Muri 两人在玩一个游戏:两人轮流进行操作,最先不能进行操作者输。

一次操作定义为:操作者选择一个杯子 \(i\),从中喝掉 \(x_i\) 升水。对于两个人,都要满足 \(x_i\in[l_i,\min(r_i,W_i)]\),且对于 Yuri 要满足 \(x_i\) 是有理数、对于 Muri 要满足 \(x_i\) 是无理数

现在,Muri 可以选择先后手,若两人以最优策略行动,问谁会获胜。

思路

我们发现,在一定的精度内,相距很近的有理数与无理数之间对胜负性的影响并不大,胜负状态间的转折点只是一些整数点,于是可以把 Yuri 和 Muri 的取数值域分别看做是 \([l_i,r_i]\) 和 \((l_i,r_i)\)。如下图(表示进行一次操作之后能得到的 \(W^\prime_i\)。上面为 Yuri 的,下面为 Muri 的,下同):


接下来我们尝试打表这个博弈的 SG 函数。

以 Yuri 为例。我们发现,当 \(r_i\) 足够大时,前一部分的 SG 具有一定的规律性:

  • 若 \(W_i\in [0,l_i)\),此时无法进行操作,SG 为 \(0\);
  • 若 \(W_i\in [l_i,2l_i)\),此时可以转移到 SG 为 \(0\) 的部分,故 SG 为 \(1\);
  • 若 \(W_i\in [2l_i,3l_i)\),此时可以转移到 SG 为 \(0\) 和 \(1\) 的部分,故 SG 为 \(2\);
  • ……

所以,在 \(W_i\) 较小的时候,SG 呈现这样一个“阶梯”形。等到遇到了 \(r_i\),SG 又会有相应的改变。取整数 \(t\),满足 \(tl_i < l_i+r_i\le (t+1)l_i\),那么,继续分类讨论:

  • 若 \(W_i\in[tl_i,l_i+r_i)\),根据上面,SG 为 \(t\);
  • 若 \(W_i\in[l_i+r_i,2l_i,r_i)\),此时,如下图,无法转移到 SG 为 \(0\) 的部分,故 SG 为 \(0\);
  • 若 \(W_i\in[2l_i+r_i,3l_i,r_i)\),此时无法转移到 SG 为 \(1\) 的部分,故 SG 为 \(1\);
  • ……

如此下去,得到 Yuri 的最终的 SG 如下图:

同理,我们可以得到 Muri 的 SG,总体如下图所示,它与 Yuri 的只在某些整点处的取值略有不同,大体上是一样的,这也是为什么我们可以把取数值域进行近似的原因。

下称 SG 突变的点为转折点,即满足 \(l_i\ |\ W_i\bmod(l_i+r_i)\) 的点。


那么,对于这个非公平的博弈,SG 是否仍然有用呢?显然是有的。在非转折点上,SG 仍然可以判断胜负性,若 SG 为 \(0\) 则先手必败,否则先手必胜。在转折点上的情况下面会讲。

注意到在本题中,Muri 取数值域为 Yuri 取数值域的真子集,所以若在 Muri 的视角下其是必败的(故下面两种情况下的“SG”指的是 Muri 的),Yuri 可以只用 Muri 的取数值域让其必败。故,在「SG 为 \(0\) 且 Muri 先手」或「SG 不为 \(0\) 且 Yuri 先手」时 Yuri 必胜。


上面提到在转折点上,SG 可能不奏效。在官方题解中,定义了包括这些转折点在内的一类点,称为“「不正」点”,根据 std,本文中将其翻译为“作弊点”。若此时水量在作弊点,那么 Yuri 可以通过操作改变 SG 对自己的不利。作弊点有以下两类:

  1. 所有转折点,即满足 \(l_i\ |\ W_i\bmod(l_i+r_i)\) 的点。

    此时若 Yuri 先手,假设此时有 \(p(l_i+r_i)+ql_i\) 的水,SG 为 \(q\),其可以选择喝 \(l_i\) 的水,此时水量 \(W=p(l_i+r_i)+(q-1)l_i\),SG 为 \(q-1\),但是,此时 Muri 操作后能够到达的 \(W\in((p-1)(l_i+r_i)+ql_i,p(l_i+r_i)+(q-2)l_i)\),没有 SG 为 \(q\) 的点,所以就无法保证必胜。

  2. \(W\in[2l_i,l_i+r_i]\cap\mathbb{Q}\) 中的点。
    此时 Yuri 可以把水量转移到 \(l_i\) 从而保证必胜,因为此时只有其可以操作这杯水。注意一定得是有理的,有人忘了这个前提以为自己 hack 了 std。

于是,我们可以判断,若为「SG 为 \(0\) 且 Yuri 先手」的情况,若其中有作弊点,则 Yuri 必胜,否则 Muri 必胜。若为 「SG 不为 \(0\) 且 Muri 先手」的情况,则若 Muri 第一步能保证去除所有作弊点,则 Muri 必胜,否则 Yuri 必胜。注意这里的 SG 也应该在 Muri 的视角下,因为作弊点是对于 Yuri 而言的。


所以,整个过程我们只需要统计初始 Muri 视角下的 SG 和,然后判断是否有 Muri 必胜的情况,若有则 Muri 必胜,否则 Yuri 必胜。


#include<iostream>
#include<cstdio>
#define maxn 200005
using namespace std;
int n,w[maxn],l[maxn],r[maxn],sg[maxn],sgsum=0;
int main(){
      scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d%d",&w[i],&l[i],&r[i]);
      for(int i=1;i<=n;i++){int res=w[i]%(l[i]+r[i]); sgsum^=(sg[i]=max(0,((res-1)/l[i])));} // calculate sgsum
      if(sgsum==0){ // Muri can win if and only if there's no "cheating point"
            bool flag=0; for(int i=1;i<=n&&!flag;i++){
                  int res=w[i]%(l[i]+r[i]);
                  flag|=((res%l[i]==0)||(w[i]<l[i]+r[i]&&w[i]>=2*l[i])); // determine if there's "cheating point"
            } if(flag) printf("Yuri"); else printf("Muri");
      }else{ // Muri can win if and only if there's one way to make sgsum==0 and there's no "cheating point"
            int num=0,pos=0; for(int i=1;i<=n;i++)
                  {int res=w[i]%(l[i]+r[i]); if((res%l[i]==0)||(w[i]<l[i]+r[i]&&w[i]>=2*l[i])){num++; pos=i;}}
            if(num>1){printf("Yuri"); return 0;} // Muri will never win since the number of "cheating point" > 1
            if(num==0){printf("Muri"); return 0;}// if there's no "cheating point", Muri can always win
            // otherwise, if there's exactly one "cheating point"
            int res=sgsum^sg[pos],mmax=(l[pos]+r[pos]-1)/l[pos]; // new grundy number and maximum grundy number
            if(res>mmax){printf("Yuri"); return 0;} // new grundy number won't exist
            int left=res*l[pos],right=min(res*l[pos]+l[pos],l[pos]+r[pos]);
            int T=max(0,w[pos]/(l[pos]+r[pos])-(sg[pos]<res));
            if(w[pos]<=l[pos]+r[pos]){if((res==0||res==1)&&res<sg[pos]) printf("Muri"); else printf("Yuri"); return 0;}
            // determine if (left+T*(l+r) , right+T*(l+r)) ∩ (w-r , w-l)  
            if(!(right+T*(l[pos]+r[pos])<=w[pos]-r[pos]||left+T*(l[pos]+r[pos])>=w[pos]-l[pos]))
                  printf("Muri"); else printf("Yuri");
      }
      return 0;
}
/*
2
16 3 5
7 5 6

2
17 3 7
10 3 7
*/

标签:Muri,int,题解,pos,必胜,Yuri,SG
From: https://www.cnblogs.com/qzhwlzy/p/17725958.html

相关文章

  • 【POJ 3253】Fence Repair 题解(贪心算法+优先队列+哈夫曼树)
    农夫约翰想修理牧场周围的一小段围栏。他测量了围栏,发现他需要N(1≤N≤20000)块木板,每块木板都有一定的整数长度Li(1≤Li≤50000)单位。然后,他购买了一块长度刚好足以锯入N块木板的长木板(即,其长度为Li长度的总和)。FJ忽略了“切口”,即锯切时锯屑损失的额外长度;你也应该忽略它。FJ伤心地......
  • S16.23.12.2. 集合论 题解
    原题连接可以发现集合对称差就是异或运算。每个点都记一个长度为值域的bitset,每一位都表示根到他有没有奇数个这个数字。那么\(a_x\)改为\(v\)的修改就变成了修改子树的所有点的bitset,每次将子树中所有点的第\(a_x\)位取反,再将第\(v\)位取反。查询就是\(u\)的\(b......
  • springBoot上传文件时MultipartFile报空问题解决方法
    1.问题描述:之前用springMVC,转成springboot之后发现上传不能用。网上参考说是springboot已经有CommonsMultipartResolver了,但是我的上传后台接收的还是null。2.解决方法加入配置类importorg.springframework.context.annotation.Bean;importorg.springframework.context......
  • AT_abc321_f [ABC321F] #(subset sum = K) with Add and Erase 题解
    AT_abc321_f[ABC321F]#(subsetsum=K)withAddandErase题解题目大意现在有一个空箱子。给你两个数\(Q,K\),然后给你\(Q\)行,每一行代表一个操作:\(+x\),即向箱子里加一个权值为\(x\)的小球。\(-x\),即从箱子里把权值为\(x\)的小球拿一个出来。保证合法,即箱子......
  • CF877F 题解
    CF877F题解更好的阅读体验提供一个扫描线+根号分治做法。首先,可以把题目的条件转化成求$sum_r-sum_{l-1}=k$的区间数。考虑扫描线,当区间的右端点从$r-1$移动到$r$时,新增的区间的左端点就是所有满足$sum_{l-1}=sum_r-k,l\ler$的$l$。这时我们对$sum_{l-1}$......
  • 【问题解决】shell脚本执行错误 $‘\r‘:command not found
    问题原因:在Windows中,换行符是由回车符(\r)和换行符(\n)组成的,而在Unix/Linux等系统中,只使用换行符(\n)作为换行标志。当你在Unix/Linux系统上运行一个包含Windows格式换行符的脚本时,Shell会尝试解释其中的回车符,导致错误提示$‘\r’:commandnotfound。这是因为Shell将回......
  • [COCI2016-2017#4] Osmosmjerka 题解
    [COCI2016-2017#4]Osmosmjerka题解我们发现对于每个点,只有八个方向,也就是说,最终能得到的字符串只会有\(8nm\)个,那我们可以考虑把这些字符串的哈希值求出来,相同的哈希值代表选到相同字符串的一种可能,直接统计即可。现在的问题就在于,怎么快速地求出这\(8nm\)个字符串的哈希......
  • 题解 CF1257G【Divisor Set】
    problem我们说一个集合\(D\)是一个好的集合,当不存在集合中的两个不同元素\(a,b\)使得\(a\)是\(b\)的约数。给定一个超大整数的素数表示形式\(N=\prod_{i=1}^n{p_i}\),要求从它的所有因子中选择尽可能多的元素组成一个好的集合。问这个最大的size是多少,输出模99824......
  • 题解 ARC165F【Make Adjacent】
    区间排序问题,主席树优化建图,最小字典序拓扑排序(priority_queue)problem给定一个长度为\(n*2\)的序列,其中每种元素恰好出现了2次。允许每次选择任意两个相邻的元素交换。那么必定存在一个最小\(k\):使得\(k\)次交换以后所有相同的元素都是相邻的。问恰好操作\(k\)次后,......
  • 【POJ 1521】Entropy 题解(贪心算法+优先队列+哈夫曼树)
    熵编码器是一种数据编码方法,通过对删除了“浪费”或“额外”信息的消息进行编码来实现无损数据压缩。换句话说,熵编码去除了最初不需要的信息,以准确编码消息。高度的熵意味着一条消息包含大量浪费的信息;以ASCII编码的英文文本是具有极高熵的消息类型的示例。已经压缩的消息,如JPEG图......