【题目描述】

对于一个元素介于 \([0,2^m)\) 且互不相同的长度为 \(n\) 的序列 \(a_1, a_2 ...,a_n\) ,定义它的特征序列为 \(p_0,p_1,...,p_{2^m-1}\) ,其中 \(p_i\) 表示使得 \(a_{p_i}\) 与 \(i\) 的异或值最大的下标。

​ 形式化地,定义 $ p_i=\arg \max\limits_{1<=j<=n} a_j \oplus i $

给定一个特征序列 \(p\) ,求有多少个满足要求的原序列 \(a\) 可以得到这个特征序列。

​ 答案对 \(10^9+7\) 取模

【样例】

【样例输入1】
6 3
1 1 2 2 3 4 5 6
【样例输出1】
4

【解析】

首先明确,合法的 \(p\) 中,必定出现完整的 \([1,n]\)

将\([0,2^m-1)\) 的二进制形式依次写出(取 \(m=3\) )

000 001 010 011 100 101 110 111

发现每次取一半,在第 \(k\) 次时,会使从高到底第 \(k\) 为发生 \(0,1\) 分割

所以考虑分治:

设状态 \([l,r]\) 表示在 \([l,r]\) 中,任意 \(a_{p_i} \oplus i\) 的前 \(dep\) 位相同, \(dep\) 表示分治深度。

其实这也代表了 \(a_{p_i}\) 前 \(dep\) 位相同,这个可以从之前的例子中看出。

接下来考虑下一层:

  1. 若集合 \(p_{l,..,mid}=p_{mid+1,..,r}\) 则表示下一位这两边也相同,则将方案数乘二,问题规模减半

  2. 若集合 \(p_{l,..,mid}!=p_{mid+1,..,r}\) 则代表下一位不同,且可以得出 \(a_{l,..,mid}\) 的 \(dep\) 位一定为 \(1\) , \(a_{mid+1,..,r}\) 的 \(dep\) 位一定为 \(0\),因为要保持最大且左区间的 \(dep\) 位均为 \(0\) ,右区间均为 \(1\) 所以有以上结论。之后这两种情况就独立了,乘法原理直接乘起来就可以了。

    考虑无解,即集合 \(p_{l,..,mid}!=p_{mid+1,..,r}\) 但 \(p_{l,..,mid}\cap p_{mid+1,..,r}!=\varnothing\) 就无解。

【CODE】

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn = (1<<16)+33;
inline ll read_int(){
ll a=0;bool f=0;char g=getchar();
while(g<'0'||'9'<g) {if(g=='-') f=1;g=getchar();}
while('0'<=g&&g<='9') a=a*10+g-'0',g=getchar();
return f ? -a : a;
} inline void write(ll a,bool b=1){
if(a<0) a=-a,putchar('-');
ll lin[30],top=0;
while(a) lin[++top]=a%10,a/=10;
if(top==0) lin[++top]=0;
while(top) putchar(lin[top--]+'0');
if(b) putchar('\n');
} ll n,m,mod=1e9+7;
ll sj[maxn];
ll vis[maxn]; inline ll fz(ll l,ll r){
// cout<<l<<" "<<r<<endl;
if(l==r) return 1;
ll mid=(l+r)>>1;
int bt=0,xd=0;
set<int> a,b;
int f=0;
for(int i=l;i<=mid;i++) a.emplace(sj[i]);
for(int i=mid+1;i<=r;i++) b.emplace(sj[i]),f= (f||(a.find(sj[i])!=a.end()) ? 1 : 0);
if(f&&a!=b) return 0;
if(a==b) return (ll)2*fz(l,mid)%mod;
else return fz(l,mid)*fz(mid+1,r)%mod;
} inline void read(){
n=read_int(),m=read_int();
for(int i=1;i<=(1<<m);i++) sj[i]=read_int(),vis[sj[i]]=1;
for(int i=1;i<=n;i++){
if(vis[i]==0) {write(0);return;}
}
write(fz(1,(1<<m)));
} int main (){
// freopen(".out","w",stdout);
read();
// while(1) getchar();
}

【后记】

如有大佬知道之前那个合法的 \(p\) 中必有 \([i,n]\) 是如何证明的,请留言

【2022noip多校】异或的更多相关文章

  1. NFLSOJ 1072 - 【2021 六校联合训练 NOIP #1】异或(FWT+插值)

    题面传送门 一道非常不错的 FWT+插值的题 %%%%%%%%%%%% 还是那句话,反正非六校的看不到题对吧((( 方便起见在下文中设 \(n=2^d\). 首先很明显的一点是这题涉及两个维度:异或和 ...

  2. 2015 多校联赛 ——HDU5416(异或)

    CRB has a tree, whose vertices are labeled by 1, 2, …, N. They are connected by N – 1 edges. Each ed ...

  3. 2020牛客暑期多校训练营(第五场)B - Graph (异或 最小生成树 分治 Trie)

    B - Graph 题目链接 每次操作不会改变两点之间的路径异或和 以 1 号点为起点,算出任意一点到 1 号点的异或值 dis[i](把该值当做 i 号点权值), 那么任意两点的异或值为 \(dis ...

  4. GPS校时器,GPS时钟装置,NTP网络时间服务器

    GPS校时器,GPS时钟装置,NTP网络时间服务器 GPS校时器,GPS时钟装置,NTP网络时间服务器 GPS校时器,GPS时钟装置,NTP网络时间服务器 GPS校时器,GPS时钟装置,NTP网络时间 ...

  5. 2018 HDU多校第三场赛后补题

    2018 HDU多校第三场赛后补题 从易到难来写吧,其中题意有些直接摘了Claris的,数据范围是就不标了. 如果需要可以去hdu题库里找.题号是6319 - 6331. L. Visual Cube ...

  6. [多校联考2019(Round 5 T1)] [ATCoder3912]Xor Tree(状压dp)

    [多校联考2019(Round 5)] [ATCoder3912]Xor Tree(状压dp) 题面 给出一棵n个点的树,每条边有边权v,每次操作选中两个点,将这两个点之间的路径上的边权全部异或某个值 ...

  7. dfs套异或的包含性——cf986C好

    很好的题,想了半天,官方题解的解法更好 这种异或问题的包含性在北邮的校赛里就出现过,需要认真学习一下 /* y和所有合法的x合并,如果没有剪枝,那么复杂度爆炸总共要判(2^n*2^n) 可以考虑如下优 ...

  8. HDU6579 2019HDU多校训练赛第一场1002 (线性基)

    HDU6579 2019HDU多校训练赛第一场1002 (线性基) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6579 题意: 两种操作 1.在序列末 ...

  9. xdoj 2020校赛复盘

    平时写东西都不喜欢复盘,这肯定不是一个好习惯,感觉每次花好几个小时甚至好几天写题目然后没写出来也不去看题解是一种很蠢的行为( 花了这么久时间打校赛,虽然水平很low,数据结构也不太会用,还是记录一下自 ...

  10. Android数据加密之异或加密算法

    前言: 这几天被公司临时拉到去做Android IM即时通信协议实现,大致看了下他们定的协议,由于之前没有参与,据说因服务器性能限制,只达成非明文传递,具体原因我不太清楚,不过这里用的加密方式是采用异 ...

随机推荐

  1. PyTorch+昇腾 共促AI生态创新发展

    原文链接: https://mp.weixin.qq.com/s/s8jNzTo0DM_LjyUwYDVgGg ============================================ ...

  2. 【转载】手动DIY制作机械臂

    相关链接: https://news.cnblogs.com/n/703664/ https://www.bilibili.com/video/BV12341117rG https://www.cnb ...

  3. ComfyUI插件:ComfyUI-BrushNet节点

    前言: 学习ComfyUI是一场持久战,而ComfyUI-BrushNet是最近的局部重绘节点,其包含BrushNet和Powerpaint两个主要节点,其中BrushNet有SD1.5和SDXL两个 ...

  4. 【CMake系列】09-cmake install 一般文件 文件夹 代码文件

    上一节,我们学习了项目构建后.目标的安装,本节学习的内容是 对于一般文件,文件夹以及源代码的安装 本节的文件依然使用 file(WRITE xxx.xx) 来创建,不依赖额外的文件 本专栏的实践代码全 ...

  5. 推荐5款免费、开箱即用的Vue后台管理系统模板

    前言 在现今的软件开发领域,Vue凭借其高效.灵活和易于上手的特性,成为了前端开发的热门选择.对于需要快速搭建企业级后台管理系统的开发者而言,使用现成的Vue后台管理系统模板无疑是一个明智之举.本文大 ...

  6. uni-app 解析支付宝form表单,h5 app唤起支付宝

    1.通过接口拿到form表单 code为后端返回的form表单数据: document则是使用 document.querySelector('body').innerHTML 生成的html页面: ...

  7. SNAT 与 DNAT

    本文为博主原创,转载请注明出处: SNAT(Source Network Address Translation,源网络地址转换)和DNAT(Destination Network Address T ...

  8. ChatGPT介绍与使用场景

    ChatGPT是OpenAI开发的一款基于GPT-3和GPT-4的人工智能聊天机器人."GPT"代表的是"Generative Pre-trained Transform ...

  9. 推荐3款卓越的 .NET 开源搜索组件库

    前言 最近有不少同学提问:.NET有哪些开源的搜索组件库可以推荐的吗?,今天大姚给大家推荐3款卓越的 .NET 开源搜索组件库,希望可以帮助到有需要的同学. Elasticsearch .NET El ...

  10. C++11新初始化方法 使用{}初始化变量

    列表初始化 在C++11及以后的版本中,使用{}来初始化变量是一种新的初始化方法,称为列表初始化(List Initialization).这种初始化方法可以用来初始化内置类型.自定义类型以及聚合类型 ...