【比赛题目】匹配最大异或

【比赛题目】匹配最大异或

在这里插入图片描述
在这里插入图片描述
感觉非常妙

我第一眼看到题,没什么思路,直接奔着部分分去了……
正解的思路就是分治。考虑将[0,2m -1]分成[0,2m-1-1]和[2m-1 ,2m -1]两部分,发现这两组数字中如果不看最高位,就是两个一模一样的序列。也就是说,0与2m-1对应,1与2m-1 +1对应,以此类推,每一个数字都有与之对应的、仅有最高位不同的数字,称这样的两个数字为 一对数字。那么我们考虑对最高位分情况讨论:

  • 如果X序列所有数字最高位均相同,那么由于 一对数字除了最高位都一样,而最高位并不能导致这两个数字的P值产生差异,所以会有充要条件:每对数字的P值相等。那么我们只需要考虑[0,2m-1 ]范围内的P值即可,最后情况数的二倍即为总情况数。
  • 如果最高位既有0又有1,由于前一部分必定选择最高位为1的X值而后半部分必定选择最高位为0的数字,所以有充要条件:每对数字P值必定不等。那么我们确定了每一位X值的最高位,最高位不再需要考虑。将前一部分与后一部分分别递归求解,情况数相乘即为答案。
  • 我们看到前面的两种情况包含了所有合法情况,所以如果出现其他情况,说明不存在合法序列,输出0

于是就是O(nlog(n)的分治了。
代码极其简单,思维比较难想(对我来说)

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define re register
typedef long long LL;
il int read(){
	int s=0,w=1;char c=getchar();
	while(c<'0'||c>'9'){ if(c=='-') w=-1;c=getchar();}
	while(c>='0'&&c<='9'){ s=(s<<1)+(s<<3)+c-'0';c=getchar();}
	return s*w;
} 
const int N=1<<17;
const LL mod=1e9+7;
int m,n,num,P[N];
il LL solve(int l,int r){
	if(l==r) return 1;//说明前面m-1位均已固定,此处只有一种可能
	int mid=l+r>>1,cnt=0;
	for(re int i=l,j=mid+1;i<=mid;++i,++j) cnt+=(P[i]==P[j]);
	if(!cnt) return solve(l,mid)*solve(mid+1,r)%mod;
	if(cnt==mid-l+1) return solve(l,mid)*2%mod;
	return 0;
	
}
int main()
{
	freopen("match.in","r",stdin);
	freopen("match.out","w",stdout);
	m=read(),n=read(),num=1<<m; 
	for(re int i=0;i<num;++i) P[i]=read();
	printf("%lld",solve(0,num-1));
	
}
/*
3 6
1 1 2 2 3 4 5 6

4
*/
/*
2 3
1 2 1 3

0
*/
/*
3 8
1 2 3 4 5 6 7 8
1
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值