题目描述
一姬想要设计一种机器,使自己不断地和牌上分,但是她觉得麻将是可以让四个人都得到快乐的,至少她不希望雀魂玩家减一这种事情的发生。因此她不希望有人被飞,所以她想要你设计一款三倍满自动机,使得自己在闲家和牌收益最大又不会让人被飞。
由于她只和三倍满,所以做出决策以及提高打点是十分重要的,在自动机中,这需要解决以下问题实现:
给定n个非负整数 a1a_1a1,a2a_2a2,a3a_3a3,a4a_4a4… ,给定一个非负整数x,求a[i]a[i]a[i]⨁\bigoplus⨁a[j]a[j]a[j] ⨁\bigoplus⨁xxx的最大值,其中 ⨁\bigoplus⨁表示异或运算。
输入格式
第一行一个正整数nnn和一个非负整数xxx 。
第二行nnn个非负整数表示aia_iai 。
输出格式
输出一行一个非负整数表示答案。
样例
样例输入
3 4
3 5 7
样例输出
6
数据范围与提示
2≤\leq≤nnn≤\leq≤10610^6106
0≤\leq≤aia_iai≤\leq≤10910^9109
0≤\leq≤xxx≤\leq≤10910^9109
分析
这道题求的是三个数的异或和,那么自然而然地可以联系到
The XOR Largest Pair这道题,不同的是,我们要求两个数再异或x的最大值
在那道题中,我们把每个数的二进制表示存入Trie树中,并从高位到低位枚举每个位,如果存在当前数字^1的数,就可以为答案做贡献
比如:当前为1,同一层还有一个0,那么两者异或后当前位就为1
本题也可以用类似思路,不过要把x的当前位参与进来
具体的,用u表示当前位,v表示x的当前位
1.u=1,v=1,1^1=0,则另一位为1,使得0 ^1=1
2.u=1,v=0,1^0=1,则另一位为0,使得1 ^0=1
3.u=0,v=0,0^0=0,则另一位为1,使得0 ^1=1
综上得,我们可以发现,另一位必须是(u^ v ^1),才能为当前做贡献
Code:
#include<cstdio>
#include<iostream>
using namespace std;
#define int long long
int n,x,a[10000005],t[50000005][2],cnt=1,Ans;
void build(int c)//Trie的push操作
{
int p=1;
for(int i=31;i>=0;i--)
{
int b=((c>>i)&1);
if(!t[p][b])
{
t[p][b]=++cnt;
}
p=t[p][b];
}
}
void search(int c,int ans)
{
int p=1;//注意,每次是从根节点开始跑!
for(int i=31;i>=0;i--)
{
int b=((c>>i)&1);//u
int o=b^((x>>i)&1)^1;//另一位
if(t[p][o])
{
p=t[p][o];
ans+=(1<<i);
}
else{
p=t[p][o^1];
}
}
Ans=max(Ans,ans);
}
signed main()
{
scanf("%lld%lld",&n,&x);
//build(x);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
build(a[i]);
search(a[i],0);
}
printf("%lld",Ans);
return 0;
}

本文介绍了一种设计三倍满自动机的方法,以确保在麻将游戏中不会出现玩家被飞的情况。核心问题是寻找三个非负整数a[i]的异或和最大值,其中考虑了异或运算和给定的非负整数x。通过分析和样例,提出了利用 Trie 树存储数字,并结合x的二进制位进行计算的策略,得出另一位必须为(u^ v ^1)才能最大化异或和。
2605

被折叠的 条评论
为什么被折叠?



