【比赛题目】匹配最大异或
感觉非常妙
我第一眼看到题,没什么思路,直接奔着部分分去了……
正解的思路就是分治。考虑将[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
*/