【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的二叉树的方法树等于组成左子树的方法数 乘于组成右子树的方法数再累计. & ...
随机推荐
- gcc 学习笔记(一) - 编译C程序 及 编译过程
一. C程序编译过程 编译过程简介 : C语言的源文件 编译成 可执行文件需要四个步骤, 预处理 (Preprocessing) 扩展宏, 编译 (compilation) 得到汇编语言, 汇编 (a ...
- 最多水容器(M)
题目 给定n个非负整数a 1,a 2,...,a n,其中每个代表坐标(i,a i)处的一个点.绘制n条垂直线,使得线i的两个端点处于(i,a i)和(i,0)处.找到两条线,它们与x轴一起形成一个容 ...
- TCP系列13—重传—3、协议中RTO计算和RTO定时器维护
从上一篇示例中我们可以看到在TCP中有一个重要的过程就是决定何时进行超时重传,也就是RTO的计算更新.由于网络状况可能会受到路由变化.网络负载等因素的影响,因此RTO也必须跟随网络状况动态更新.如果T ...
- win7 x64+iis7.5 配置错误:CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\7cb4f3
解决方法: 1. 将windows/temp属性-安全-高级 添加IIS_USERS用户,同时编辑权限为完全控制(写入和编辑)即可. 注意: 要确保权限添加上了,win7下有可能系统为安全,会自动取消 ...
- DAY1敏捷冲刺
站立式会议 工作安排 (1)服务器配置 (2)数据库建表 (3)页面初步样式设计 (4)主要页面之间的交互 燃尽图 代码提交记录 感想 林一心:后端云服务器的配置确实是一个挑战,目前还在摸索中 赵意: ...
- java 基础--数组--004
1,数组定义格式 String[] aa; String aa[];2,二位数组的定义格式1 String aa[][] = new String[m][n]; String[] aa[] = new ...
- 第20天:京东nav、footer部分制作
一.鼠标的4种状态 cursor:pointer; 鼠标变成小手cursor:default;小白cursor:move;移动cursor:text;文本输入 二.网页布局:1.input.butto ...
- CCS3 动画-鼠标放上去放大背景图片
---〉 效果如上,一个简单的过渡放大效果, <!DOCTYPE HTML> <html> <body> <style> #test{ width:30 ...
- 【bzoj5107】[CodePlus2017]找爸爸 dp
题目描述 给出两个基因串,你需要在其中插入任意个空格,使得两个串长度相同.如果两个串的某同一位置都是字母则获得某给定收益,对于每个串的每个长度为k的连续空格段要付出a(k-1)+b的损失.求最大净收益 ...
- POJ2187:Beauty Contest——题解
http://poj.org/problem?id=2187 题目大意:给n个点,求点对最大距离的平方. ———————————————————— 很容易证明最大距离的点对在最大凸包上. 那么就是旋转 ...