【spoj1182/usaco-Cow Queueing, 2003 Dec-二进制编号】数位dp
题意:定义新的排序:先按一个数中二进制中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(输入是十进制)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std; typedef long long LL;
const int N=;
const LL MX=(1LL<<);
LL X,Y,K,c[N][N]; void myswap(LL &x,LL &y){LL t;t=x;x=y;y=t;return;} void find_c()
{
memset(c,,sizeof(c));
c[][]=;
for(int i=;i<=;i++)
{
c[i][]=;
for(int j=;j<=i;j++) c[i][j]=c[i-][j]+c[i-][j-];
}
} LL find_k(LL x,int ind,int k)//0~x how many numbers has k '1's;
{
if(ind== && k==) return ;
if(x< || ind== || k<) return ;
LL t=1LL<<(ind-);
if(x&t) return c[ind-][k]+find_k(x,ind-,k-);
else return find_k(x,ind-,k);
} int main()
{
freopen("a.in","r",stdin);
// freopen("me.out","w",stdout);
int T;
scanf("%d",&T);
find_c();
while(T--)
{
scanf("%lld%lld%lld",&X,&Y,&K);
if(X<) X=MX+X;
if(Y<) Y=MX+Y;
if(X>Y) myswap(X,Y); LL sum=,ind=,now,k;
for(int i=;i<=;i++)
{
now=find_k(Y,,i)-find_k(X-,,i);
if(sum+now<K) sum+=now,ind=i;
else {k=K-sum;break;}
}
ind++;
// printf("ind = %lld k = %lld\n",ind,k);
LL l=X,r=Y,mid;
while(l<r)
{
mid=(l+r)/;
now=find_k(mid,,ind)-find_k(X-,,ind);
// printf("mid = %lld now = %lld %lld\n",mid,now,find_k(mid,32,ind));
if(now<k) l=mid+;
else r=mid;
}
printf("%d\n",l); }
return ;
}
usaco (usaco上输入输出都是二进制形式)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std; typedef long long LL;
const int N=;
const LL MX=(1LL<<);
LL X,Y,K,c[N][N],d[N],bit[N];
char s[]; void myswap(LL &x,LL &y){LL t;t=x;x=y;y=t;return;} void find_c()
{
memset(c,,sizeof(c));
c[][]=;
for(int i=;i<=;i++)
{
c[i][]=;
for(int j=;j<=i;j++) c[i][j]=c[i-][j]+c[i-][j-];
}
} LL find_k(LL x,int ind,int k)//0~x how many numbers has k '1's;
{
if(ind== && k==) return ;
if(x< || ind== || k<) return ;
LL t=1LL<<(ind-);
if(x&t) return c[ind-][k]+find_k(x,ind-,k-);
else return find_k(x,ind-,k);
} LL read()
{
scanf("%s",s);
LL x=;int l=strlen(s);
for(int i=l-;i>=;i--)
{
if(s[i]=='') x+=bit[l-i-];
}
return x;
} int main()
{
// freopen("a.in","r",stdin);
freopen("cowq.in","r",stdin);
freopen("cowq.out","w",stdout);
find_c();
bit[]=;
for(int i=;i<=;i++) bit[i]=bit[i-]*; X=read();
Y=read();
scanf("%lld",&K);
// printf("X = %lld Y = %lld\n",X,Y);
// scanf("%lld",&X,&Y,&K);
if(X<) X=MX+X;
if(Y<) Y=MX+Y;
if(X>Y) myswap(X,Y); LL sum=,ind=,now,k;
for(int i=;i<=;i++)
{
now=find_k(Y,,i)-find_k(X-,,i);
if(sum+now<K) sum+=now,ind=i;
else {k=K-sum;break;}
}
ind++;
// printf("ind = %lld k = %lld\n",ind,k);
LL l=X,r=Y,mid,p=find_k(X-,,ind);
while(l<r)
{
mid=(l+r)/;
now=find_k(mid,,ind)-p;
// if(now<k) l=mid+1;
if(now<k) l=mid+;
if(now>=k) r=mid;
}
// printf("%d\n",l);
int x=;
while(l)
{
d[++x]=l%;
l/=;
}
for(int i=x;i>=;i--) printf("%d",d[i]);printf("\n");
return ;
}
【spoj1182/usaco-Cow Queueing, 2003 Dec-二进制编号】数位dp的更多相关文章
- Pair(二进制处理+数位dp)(2019牛客暑期多校训练营(第七场))
示例: 输入: 33 4 24 5 27 8 5 输出:5 7 31 题意:存在多少对<x,y>满足x&y>C或x^y<C的条件.(0<x<=A,0< ...
- bzoj3209 花神的数论题 (二进制数位dp)
二进制数位dp,就是把原本的数字转化成二进制而以,原来是10进制,现在是二进制来做,没有想像的那么难 不知到自己怎么相出来的...感觉,如果没有一个明确的思路,就算做出来了,也并不能锻炼自己的能力,因 ...
- BZOJ3329: Xorequ(二进制数位dp 矩阵快速幂)
题意 题目链接 Sol 挺套路的一道题 首先把式子移一下项 \(x \oplus 2x = 3x\) 有一件显然的事情:\(a \oplus b \leqslant c\) 又因为\(a \oplus ...
- 数位dp(二进制01问题)
http://poj.org/problem?id=3252 题意:给你一个区间,求区间有多少个满足条件的数.条件是:把该数转为二进制后,如果0的数量大于等于1的数量,则为满足条件的数量. 题解:数位 ...
- hdu5432Rikka with Array (数位dp+十进制转化为二进制)
Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, so he ...
- USACO Cow Contest
洛谷 P2419 [USACO08JAN]牛大赛Cow Contest https://www.luogu.org/problemnew/show/P2419 JDOJ 2554: USACO 200 ...
- USACO Cow Cars
洛谷 P2909 [USACO08OPEN]牛的车Cow Cars https://www.luogu.org/problemnew/show/P2909 JDOJ 2584: USACO 2008 ...
- USACO Cow Frisbee Team
洛谷 P2946 [USACO09MAR]牛飞盘队Cow Frisbee Team 洛谷传送门 JDOJ 2632: USACO 2009 Mar Silver 2.Cow Frisbee Team ...
- USACO Cow Pedigrees 【Dp】
一道经典Dp. 定义dp[i][j] 表示由i个节点,j 层高度的累计方法数 状态转移方程为: 用i个点组成深度最多为j的二叉树的方法树等于组成左子树的方法数 乘于组成右子树的方法数再累计. & ...
随机推荐
- 重载和const参数
const仅能用于在定义函数签名时,区分是为引用定义参数,还是为指针定义参数.定义基本类型type(如int等),从重载的观点来看,const int和int是相同的. const long& ...
- go的IO函数,整理下最基本的IO处理函数,工欲善其事必先利其器
bufio.NewScanner()函数是一行一行地读,但是对/proc/函数,这里不是个好方法,最好是把所有的数据一次读完,然后再去读,有没有这样读的接口呢?把所有数据都读入到内存中然后再通过通过搜 ...
- Swift & Unicode
Swift & Unicode emoji let == const https://www.runoob.com/swift/swift-basic-syntax.html
- 第72天:jQuery实现下拉菜单
jQuery实现下拉菜单 一.居中 1.块元素居中:给块元素本身设置:margin:0 auto;,块元素必须设置宽度 2.行内块元素居中:给元素父级设置text-algin:center; < ...
- UIKit中的几个核心对象的介绍:UIApplication,UIWindow,UIViewController,UIView(layer)简单介绍
UIApplication,UIWindow,UIViewController,UIView(layer)简单介绍 一:UIApplication:单例(关于单例后面的文章中会详细介绍,你现在只要知道 ...
- CodeChef LEMOVIE
题意:给你n个数字(下标不同数值相同的数字应当被认为是不同的数字),有n!种排列方式.每种排列方式的价值定义为:第一次出现时比前面的所有数字都大的数值个数. 比如1,2,2,3这个排列中,1,2,3这 ...
- 【bzoj1579】[Usaco2009 Feb]Revamping Trails 道路升级 分层图最短路
题目描述 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i (1 < ...
- BZOJ5339:[TJOI2018]教科书般的亵渎——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5339 https://www.luogu.org/problemnew/show/P4593 小豆 ...
- BZOJ1085:[SCOI2005]骑士精神——题解+IDA*粗略讲解
http://www.lydsy.com/JudgeOnline/problem.php?id=1085 Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空 ...
- HDOJ(HDU).1166 敌兵布阵 (ST 单点更新 区间求和)
HDOJ(HDU).1166 敌兵布阵 (ST 单点更新 区间求和) 点我挑战题目 题意分析 根据数据范围和询问次数的规模,应该不难看出是个数据结构题目,题目比较裸.题中包括以下命令: 1.Add(i ...