【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的二叉树的方法树等于组成左子树的方法数 乘于组成右子树的方法数再累计. & ...
随机推荐
- 11.24Daily Scrum(3)
人员 任务分配完成情况 明天任务分配 王皓南 实现网页上视频浏览的功能.研究相关的代码和功能.1002 数据库测试 申开亮 实现网页上视频浏览的功能.研究相关的代码和功能.1003 实现视频浏览的功能 ...
- LintCode-140.快速幂
快速幂 计算an % b,其中a,b和n都是32位的整数. 样例 例如 231 % 3 = 2 例如 1001000 % 1000 = 0 挑战 O(logn) 标签 分治法 code class S ...
- TCP系列02—连接管理—1、三次握手与四次挥手
一.TCP连接管理概述 正如我们在之前所说TCP是一个面向连接的通信协议,因此在进行数据传输前一般需要先建立连接(TFO除外),因此我们首先来介绍TCP的连接管理. 通常一次完整的TCP数据传输一般包 ...
- 修改IntelliJ IDEA代码头注释
- 查询MySQL某字段相同值得重复数据
1.先查询重复的id: SELECT book_id,COUNT(*) AS COUNT FROM xs_book_source WHERE site_id=5 GROUP BY book_id HA ...
- MATLAB strcmp
比较两个输入字符串是否相等 c = strcmp(str1,str2)比较字符串 str1 与 str2 ,若完全相等则返回 1 ,不相等返回 0 str1 = 'hello'; str2 = 'he ...
- [转]matlab中squeeze函数的用法,numel的用法
squeeze的作用是移除单一维. 如果矩阵哪一个维数是1,B=squeeze(A)就将这个维数移除. 考虑2-by-1-by-3 数组Y = rand(2,1,3). 这个数组有单一维 —就是每页仅 ...
- 【bzoj5108】[CodePlus2017]可做题 拆位+乱搞
题目描述 给出一个长度为 $m$ 的序列 $a$ ,编号为 $a_1\sim a_m$,其中 $n$ 个位置的数已经确定,剩下的位置的数可以任意指定.现在令 $b$ 表示 $a$ 的前缀异或和,求 $ ...
- 封装一个jquery库
现在Javascript库海量,流行的也多,比如jQuery,YUI等,虽然功能强大,但也是不万能的,功能不可能涉及方方面面,自己写一个的JS库是对这些的补充,很多也比较实用,把应用到项目中中去也比较 ...
- 【题解】JXOI2017颜色
一眼线段树...显然,我们可以考虑最后所留下的区间,那显然这个区间中应当不能存在任何与区间外相同的颜色.这里的转化也是很常用的,我们用 \(nxt[i]\) 表示与 \(i\) 颜色相同的下一个位置在 ...