博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【spoj1182/usaco-Cow Queueing, 2003 Dec-二进制编号】数位dp
阅读量:5162 次
发布时间:2019-06-13

本文共 3165 字,大约阅读时间需要 10 分钟。

题意:定义新的排序:先按一个数中二进制中1的个数从小到大排序,如果1的个数相同则按数的大小从小到大排序。问[A,B]之间有第K大的数是哪个。-2^31<=A,B<=2^31(A,B必定同正负,负数的二进制与它相反数的二进制相加=2^32)

题解:

负数可以直接+2^31-1转化为正数。

先确定答案中1的个数:依次统计区间[m,n]内二进制表示中含1的数量为0,1,2,…的数,直到累加的答案超过k,则当前值就是答案含1的个数,假设是ind。

怎么求?就先确定当前位填什么,然后后面还有多少个1可以填,组合数弄一下。

同时,我们也求出了答案是第几个[m,n]中含ind个1的数。因此,只需二分答案,求出[m,ans]中含s个1 的数的个数进行判断即可。

这个二分需要不断往左端点靠,假设答案是ans,ans+1也含有跟ans一样的还有ind个1的数的个数。

 

 

spoj1182(输入是十进制)

 

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 using namespace std; 8 9 typedef long long LL;10 const int N=50;11 const LL MX=(1LL<<32);12 LL X,Y,K,c[N][N];13 14 void myswap(LL &x,LL &y){LL t;t=x;x=y;y=t;return;}15 16 void find_c()17 {18 memset(c,0,sizeof(c));19 c[0][0]=1;20 for(int i=1;i<=35;i++)21 {22 c[i][0]=1;23 for(int j=1;j<=i;j++) c[i][j]=c[i-1][j]+c[i-1][j-1];24 }25 }26 27 LL find_k(LL x,int ind,int k)//0~x how many numbers has k '1's;28 {29 if(ind==0 && k==0) return 1;30 if(x<0 || ind==0 || k<0) return 0;31 LL t=1LL<<(ind-1);32 if(x&t) return c[ind-1][k]+find_k(x,ind-1,k-1);33 else return find_k(x,ind-1,k);34 }35 36 int main()37 {38 freopen("a.in","r",stdin);39 // freopen("me.out","w",stdout);40 int T;41 scanf("%d",&T);42 find_c();43 while(T--)44 {45 scanf("%lld%lld%lld",&X,&Y,&K);46 if(X<0) X=MX+X;47 if(Y<0) Y=MX+Y;48 if(X>Y) myswap(X,Y);49 50 LL sum=0,ind=0,now,k;51 for(int i=0;i<=31;i++)52 {53 now=find_k(Y,32,i)-find_k(X-1,32,i);54 if(sum+now

 

 

 

 

usaco (usaco上输入输出都是二进制形式)

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 using namespace std; 8 9 typedef long long LL;10 const int N=50;11 const LL MX=(1LL<<32);12 LL X,Y,K,c[N][N],d[N],bit[N];13 char s[20];14 15 void myswap(LL &x,LL &y){LL t;t=x;x=y;y=t;return;}16 17 void find_c()18 {19 memset(c,0,sizeof(c));20 c[0][0]=1;21 for(int i=1;i<=35;i++)22 {23 c[i][0]=1;24 for(int j=1;j<=i;j++) c[i][j]=c[i-1][j]+c[i-1][j-1];25 }26 }27 28 LL find_k(LL x,int ind,int k)//0~x how many numbers has k '1's;29 {30 if(ind==0 && k==0) return 1;31 if(x<0 || ind==0 || k<0) return 0;32 LL t=1LL<<(ind-1);33 if(x&t) return c[ind-1][k]+find_k(x,ind-1,k-1);34 else return find_k(x,ind-1,k);35 }36 37 LL read()38 {39 scanf("%s",s);40 LL x=0;int l=strlen(s);41 for(int i=l-1;i>=0;i--)42 {43 if(s[i]=='1') x+=bit[l-i-1];44 }45 return x;46 }47 48 int main()49 {50 // freopen("a.in","r",stdin);51 freopen("cowq.in","r",stdin);52 freopen("cowq.out","w",stdout);53 find_c();54 bit[0]=1;55 for(int i=1;i<=31;i++) bit[i]=bit[i-1]*2;56 57 X=read();58 Y=read();59 scanf("%lld",&K);60 // printf("X = %lld Y = %lld\n",X,Y);61 // scanf("%lld",&X,&Y,&K);62 if(X<0) X=MX+X;63 if(Y<0) Y=MX+Y;64 if(X>Y) myswap(X,Y);65 66 LL sum=0,ind=0,now,k;67 for(int i=0;i<=31;i++)68 {69 now=find_k(Y,32,i)-find_k(X-1,32,i);70 if(sum+now
=k) r=mid;83 }84 // printf("%d\n",l);85 int x=0;86 while(l)87 {88 d[++x]=l%2;89 l/=2;90 }91 for(int i=x;i>=1;i--) printf("%d",d[i]);printf("\n");92 return 0;93 }

 

 

转载于:https://www.cnblogs.com/KonjakJuruo/p/6021972.html

你可能感兴趣的文章
如何显示超大图像
查看>>
spring@Resource注解
查看>>
实践语法----文件创建删除读写
查看>>
Linux学习笔记(第六章)
查看>>
Java 泛型编程
查看>>
STL简介
查看>>
Cookie/Session的机制与安全
查看>>
unbound域名解析
查看>>
Leetcode: Wiggle Sort II
查看>>
2019年春季学期第二周作业编程总结
查看>>
hadoop17---RPC和Socket的区别
查看>>
android 27 ListView
查看>>
android 30 下拉列表框:ArrayAdapter和Spinner.
查看>>
HDU 2817 A sequence of numbers
查看>>
CSS开启硬件加速来提高网站性能
查看>>
Log4j配置体验(转)
查看>>
宝马E91318D读写EDC17 C41与KESS V2 DDE8错误
查看>>
KnockOut循环绑定
查看>>
Windows API封装:LoadLibrary/FreeLibrary
查看>>
web配置详解
查看>>