二进制上的数位dpPOJ 3252
Round number POJ - 3252
题目大意:一个"round number" 数的定义是,将它转化成2进制后,0的个数大于等于1的个数,要求的就是在[s,f]范围内"round number"的个数
和之前的数位dp不同的是,这题是对二进制的数位进行dp,所以就存在着一个限制,前面有没有存在1,如果前面没有1.那么像00001,就是1,前面的0是不计数的,所以重点就在于考虑这个dfs时就得分前面有没有1,如果没有那么0就不计数,反之我们记录0和1的差值,取0加1,取1减1,不过需要注意的是,差值可能是负数,所以要转正数,详情见代码
#include<cstdio>
#include<cstring>
#define ll long long
const int N=;
int up[N];
ll n,s,f,dp[N][*N][];//dp[i][j][k]代表当前为第i位,前面0和1的差值为j-N,前面有没有1的结果
//例如dp[4][50][1]就代表第4位,在第4位前面0和1差值为0,并且前面有1的结果数
ll dfs(int p,int d,bool is1,bool isu)//p 位数,d 0和1的差值,is1 该位前面有没有1 isu有没有上限
{
if(!p)//边缘状态,0大于等于1(d>=0)返回1,反之返回0
return d>=;
if(-d>p)//小剪枝,如果剩下位数全是0加起来都没有1多,返回0
return ;
if(!isu&&dp[p][d+N][is1]!=-)
return dp[p][d+N][is1];
ll ans=;
for(int i=;i<=(isu ? up[p] : );i++)
{
if(is1)//当前面有1正常记录0的差值
ans+=dfs(p-,(i ? d- : d+),is1||i,isu&&i==up[p]);
else//当前面没有1,0不计,1记-1
ans+=dfs(p-,-i,is1||i,isu&&i==up[p]);
}
if(!isu)
dp[p][d+N][is1]=ans;
return ans;
}
ll solve(ll x)
{
int num=;
while(x)
{
up[++num]=x&;
x>>=;
}
return dfs(num,,,);
}
int main()
{
ll s,f;
memset(dp,-,sizeof(dp));
while(~scanf("%lld%lld",&s,&f))
printf("%lld\n",solve(f)-solve(s-));
return ;
}
RNGRNGRNG
关于结果的存储,不同的想法具体的dp还有也不同,有些是dp[i][j][k]是当前是第i位,前面0的个数为j,前面1的个数为k的结果有多少个,不过大体的思路还是相同的
除数位dp外,还有一个组合数学的解法,不过相比大佬们,我的思路有点麻烦,详情见代码
#include<cstdio>
#include<cstring>
#define ll long long
ll n,m,c[][]={},a[]={};//c组合数,a[i]长度为i,首位1在第i位存在RN的个数
//比加a[1]保存1,a[2]保存10,11,a[3]保存100,101,110,111,中满足RN的个数
//所以a[1]=0,a[2]=1,a[3]=1
int up[]={};
void init()
{
for(int i=;i<=;i++)
{
c[i][]=;
for(int j=;j<=i;j++)
{
if(j<=i/)
c[i][j]=c[i-][j-]+c[i-][j];
else
c[i][j]=c[i][i-j];
}
for(int j=i-;j>=(i+)/;j--)//首位i是1,剩下i-1位0可以i-1个,
//i-2个,假设最少取j个满足要求,那么j>=(i+1)/2(0的数目大于等于总数目的一半)
a[i]+=c[i-][j];
}
}
ll solve(ll x)
{
int num=;
while(x)
{
up[++num]=x&;
x>>=;
}
ll ans=;
for(int i=;i<num;i++)
ans+=a[i];
//假如x转化成2进制是1101
//先算上1,10~11,100~111的里的答案
if(num>)//先把1000算上
ans++;
int z=;//记录第i位前0的个数
//再来计算1000~1101之间的答案,down代表有没有计算到下界
//一开始的下界就是1000
for(int i=num-,down=;i>=;i--)
{
if(up[i])//当存在1时,例如第二位就是1,我们就求的是1000~1100的答案
{
if(down)//因为之前已经算过1000了,所以这里减去
ans--,down=;
for(int j=i-;z+j+>=(num+)/&&j>=;j--)//假设第i位是0,前面的0加上
//第i位再加上后面取的j个0,总的0的个数要大于等于总个数
ans+=c[i-][j];
if(i-+z>=(num+)/)//假设后面的i-1全是0,0的个数大于等于总个数
ans++,down=;//那么1100可以作为下界
}
else
z++;
}
return ans;
}
int main()
{
init();
while(~scanf("%lld%lld",&n,&m))
printf("%lld\n",solve(m)-solve(n-));
return ;
}
WEWEWE
二进制上的数位dpPOJ 3252的更多相关文章
- 图片的URL上传至阿里云OSS操作(微信小程序二维码返回的二进制上传到OSS)
当我们从网络中获取一个URL的图片我们要存储到本地或者是私有的云时,我们可以这样操作 把url中的图片文件下载到本地(或者上传到私有云中) public String uploadUrlToOss ...
- ftp设置二进制上传
一个不重要的数据库,备份是用expdp导出,然后上传到ftp服务器上面.上周这个主机宕机了,要在别的数据库恢复,发现报如下错误: ORA-39001: invalid argument value O ...
- bzoj 3209 花神的数论题——二进制下的数位dp
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3209 可以枚举 “1的个数是...的数有多少个” ,然后就是用组合数算在多少位里选几个1. ...
- 前端上传图片 base64转二进制上传
var dataURItoBlob = function (dataURI) { var byteString = atob(dataURI.split(',')[1]); var mimeStrin ...
- 浅谈数位DP
在了解数位dp之前,先来看一个问题: 例1.求a~b中不包含49的数的个数. 0 < a.b < 2*10^9 注意到n的数据范围非常大,暴力求解是不可能的,考虑dp,如果直接记录下数字, ...
- BZOJ3329 Xorequ(数位DP)
题目大意:x xor 2x=3x(与x xor 3x=2x等价)求满足等式且小于n的x的个数,与满足等式小于2n的数的个数. 因为异或是不进位的二进制加法,那么因为结果正好和加法相同,那么说明x在二进 ...
- BZOJ 4513: [Sdoi2016]储能表 [数位DP !]
4513: [Sdoi2016]储能表 题意:求\[ \sum_{i=0}^{n-1}\sum_{j=0}^{m-1} max((i\oplus j)-k,0) \] 写出来好开心啊...虽然思路不完 ...
- 【数位DP】题集
1.[HDOJ2089] 题意:求区间内不出现4和62的数的个数 解法:模板题 2.[HDOJ3555] 题意:求区间内不出现49的数的个数 解法:模板题 3.[HDOJ5179] 题意:对于一个十进 ...
- 蒟蒻的数位DP专题总结
BZOJ 1026: [SCOI2009]windy数: 题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1026 d ...
随机推荐
- Python面试常考点之深入浅出链表操作
Python面试常考点之深入浅出链表操作 在Python开发的面试中,我们经常会遇到关于链表操作的问题.链表作为一个非常经典的无序列表结构,也是一个开发工程师必须掌握的数据结构之一.在本文中,我将针对 ...
- c++11 跨平台多线程demo和qt 静态链接(std::thread有join函数,设置 QMAKE_LFLAGS = -static)
#include <stdio.h>#include <stdlib.h> #include <chrono> // std::chrono::seconds#in ...
- Codeforces 1237D. Balanced Playlist
传送门 首先显然的,如果一个位置开始播放了两圈还没结束,那么就永远不会结束 先考虑位置 $1$ 开始播放,用一个 $multisetset$ 维护一下当前听的所有歌,直到某一首歌 $r$ 不合法了就停 ...
- VS2008提示无法打开包括文件:“afxcontrolbars.h”解决办法
主要造成这个问题的主要原因是,在打了SP1的VS2008下创建的项目放在没有打SP1的VS2008下就会报错 解决办法: 一.给VS2008打上SP1补丁即可 此方法比较彻底,但是安装较 ...
- 10 select、poll以及epoll
IO复用:为了解释这个名词,首先来理解下复用这个概念,复用也就是共用的意思,这样理解还是有些抽象,为此,咱们来理解下复用在通信领域的使用, 在通信领域中为了充分利用网络连接的物理介质,往往在同一条网络 ...
- js下载blob的形式
前端构建blob的方式就是通过服务器返回的文件来创建blob,需要知道文件在服务器的具体路径,用bob创建object url对象,添加到a标签上,然后触发,blob有两个问题,1.对浏览器有兼容性限 ...
- ES6入门三:解构
数组解构 对象解构 声明与解构相关的问题 解构与重复赋值 按需解构 默认值赋值 解构参数 解构(destructuring):结构化赋值 解构通常被看作ES6的一个结构化赋值方法,可以通过解构将数组元 ...
- RPC性能优化
优化 1:元数据共享 hessian 序列化会将两种信息写到输出流: 元数据:即类全名,字段名 值数据:即各个字段对应值(如果字段是复杂类型,则会递归传递该复杂类型 的元数据和内部字段的值数据) 在 ...
- 输出指令(echo指令和printf 命令)
Shell echo命令 Shell 的 echo 指令与 PHP 的 echo 指令类似,都是用于字符串的输出.命令格式: echo string 您可以使用echo实现更复杂的输出格式控制. 1. ...
- Windows 7上QTP11破解及java等插件破解方法
QTP11破解方法: 1.准备文件 注册机mgn-mqt82.exe 2.安装QTP11 3.运行注册机mgn-mqt82.exe 如果运行mgn-mqt82.exe 没有反应-,请注意关掉暂时关掉杀 ...