01数字排序 题解

题目描述

现有一个升序排序的N位的二进制数。
这些二进制数包含所有长度为N且这个二进制数中1的位数的个数小于等于L(L<=N)的数。
你需要输出的是第i(输入的i确保1<=i<2的N次幂)小的,长度为N,且1的位数的个数小于等于L的那个二进制数,如果还是看不懂的,可以看样例解释。
(比如:001001这样的数字,N=6,含有位数为1的个数为2)。
N<=31

输入

共一行,用空格分开的三个整数N,L,i。

输出

共一行,输出满足条件的第i小的二进制数。

样例输入

5 3 18

样例输出

10010

提示

样例解释:
1 00000
2 00001
3 00010
4 00011
5 00100
6 00101
7 00110
8 00111
9 01000
10 01001
11 01010
12 01011
13 01100
14 01101
15 01110
15 01111 (有四个1,不符条件,pass掉)
16 10000
17 10001
18 10010
19 10011

题目解析

step1:暴力

枚举答案即可。

step:优化

不难得出,在长度为 x 出现 y1 的总数为

f(x,y)=i=0yCxi

利用这个公式我们从高到低进行确定这位是取 0 还是 1 。(类似于康托展开的感觉)
最后记得计算排列的时候要卡精度。
Tips: Cyx=Cyyx
32!>2621

typedef unsigned long long ull;
ll c(int x,int y){
if(y>x) return c(x,x);
ull res=1;
if(x/2<y) return c(x,x-y);
int j=1;
for(int i=x;i>=x-y+1&&j<=n;i--){
res*=(ull)i;
while(res%j==0&&j<=y) res/=j++;
}
for(;j<=y;j++) res/=(ull)j;
return res;
}

最后是代码:

#include<cstdio>
using namespace std;
typedef long long ll;
typedef long long Type;
inline Type read(){
char c=getchar();
int flag=0;
Type sum=0;
while((c<'0'||c>'9')&&c!='-') c=getchar();
if(c=='-') c=getchar(),flag=1;
while('0'<=c&&c<='9'){
sum=(sum<<1)+(sum<<3)+(c^48);
c=getchar();
}
if(flag) return -sum;
return sum;
}
ll k,n,l;
int check(int x){
int num=0;
while(x>0){
if(x&1) num++;
x>>=1;
if(num>l) return 0;
}
return 1;
}
typedef unsigned long long ull;
ll c(int x,int y){
if(y>x) return c(x,x);
ull res=1;
if(x/2<y) return c(x,x-y);
int j=1;
for(int i=x;i>=x-y+1&&j<=n;i--){
res*=(ull)i;
while(res%j==0&&j<=y) res/=j++;
}
for(;j<=y;j++) res/=(ull)j;
return res;
}
ll f(int x,int y){
if(x<y) return f(x,x);
ll res=0;
for(int i=0;i<=y;i++)
res+=c(x,i);
return res;
}
void printx(int x){
for(int i=n-1;i>=0;i--){
if(x&(1<<i)) putchar('1');
else putchar('0');
}
}
int ans[139],tmp;
int main(){
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
n=read(); l=read(); k=read();
for(int i=n;i>=1;i--)
if(f(i-1,l)>=k){
ans[i]=0;
}
else{
ans[i]=1;
k-=f(i-1,l);
l--;
}
for(int i=n;i>=1;i--) printf("%d",ans[i]);
return 0;
}
posted @   jiangtaizhe001  阅读(115)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示