【xsy1281】 珠串 打表+乱搞or数位dp
题目大意:你要找出一个有k个的本质不同的n位二进制数的集合,使得集合中最大的数最小,请输出这个数
本质不同定义:对于一个数k,rev(k), k,rev( k)与k本质相同。其中 k表示对k的每一位二进制翻转,rev(k)表示对k左右翻转。
举个例子:对于数0001,它与1000,1110,0111本质相同。
数据范围:n≤25,k≤1016。
此题貌似正解是数位dp,然而我比较菜。
看到这一题:打表啊!
于是打了个表,发现:
若k≤2⌈n2⌉−2,则直接输出k就可以了,证明显然。
若k>2⌈n2⌉−2
先考虑n为偶数的情况,我们打一个表,打出所有满足rev(x)<x或( x)<x或rev( x)<x的数,大概长这样
我们发现:以中间的分界线为界,当左侧构成的数去掉前导零后构成x,那么以x开头的不符合要求的二进制数就有2x个。
(感兴趣的同学可以证明一下,我懒得证了23333)
我们基于这一个特征,先确定这个二进制数的前n2位。
后面的n2位直接暴力枚举然后再随便判断一下就好了。
n为奇数的情况相似
以中间为分界线,当右侧横线左侧的数为x时,以x为前缀的n位二进制数有x个。
和之前的搞法一样随便搞一搞就可以了。
时间复杂度:O(2n/2),空间复杂度:O(2n/2)。
1 #include<bits/stdc++.h> 2 #define L long long 3 using namespace std; 4 5 int rev[1<<25]={0}; 6 L n,k; 7 8 void out(L k1){for(L i=0;i<n;i++) printf("%d",bool((1LL<<(n-i-1))&k1));} 9 10 void SolveEven(){ 11 L n2=n/2,s=1<<n2,all=1LL<<n; 12 if(k<s){ 13 out(k); 14 return; 15 }else k-=s; 16 for(int i=1;i<s;i++) rev[i]=(rev[i>>1]>>1)|((i&1)?(s>>1):0); 17 for(int i=1,j=2;i<s;i++,j+=2){ 18 if(k>=s-j) k-=s-j; 19 else{ 20 int p; for(p=0;p<s&&k>=0;p++){ 21 L k1=(1LL*i)<<n2|p; 22 L k2=(1LL*rev[p])<<n2|rev[i]; 23 L k3=(1LL*rev[(s-1-p)&(s-1)])<<n2|rev[s-1-i]; 24 if(k2>=k1&&k3>=k1) 25 k--; 26 } 27 L k1=(1LL*i)<<n2|(p-1); 28 out(k1); 29 return; 30 } 31 } 32 cout<<-1<<endl; 33 } 34 void SolveOdd(){ 35 L n2=n/2,s=1<<n2,all=1LL<<n; 36 L N2=(n+1)/2,S=1<<N2; 37 if(k<S-1){ 38 out(k); 39 return; 40 }else k-=S-1; 41 for(int i=1;i<s;i++) rev[i]=(rev[i>>1]>>1)|((i&1)?(s>>1):0); 42 for(int i=2,j=2;i<s;i++,j++){ 43 if(k>=s-j) k-=s-j; 44 else{ 45 int p; for(p=0;p<s&&k>=0;p++){ 46 L k1=(1LL*i)<<n2|p; 47 L k2=((i&1)<<n2)|((1LL*rev[p])<<N2)|rev[i>>1]; 48 L k3=(((i&1)==0)<<n2)|((1LL*rev[(s-p-1)&(s-1)])<<N2)|rev[s-1-(i>>1)]; 49 if(k2>=k1&&k3>=k1) 50 k--; 51 } 52 L k1=(1LL*i)<<n2|(p-1); 53 out(k1); 54 return; 55 } 56 } 57 cout<<-1<<endl; 58 } 59 60 int main(){ 61 cin>>n>>k; 62 if(n&1) SolveOdd(); 63 else SolveEven(); 64 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!