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的更多相关文章

  1. 图片的URL上传至阿里云OSS操作(微信小程序二维码返回的二进制上传到OSS)

    当我们从网络中获取一个URL的图片我们要存储到本地或者是私有的云时,我们可以这样操作  把url中的图片文件下载到本地(或者上传到私有云中)  public String uploadUrlToOss ...

  2. ftp设置二进制上传

    一个不重要的数据库,备份是用expdp导出,然后上传到ftp服务器上面.上周这个主机宕机了,要在别的数据库恢复,发现报如下错误: ORA-39001: invalid argument value O ...

  3. bzoj 3209 花神的数论题——二进制下的数位dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3209 可以枚举 “1的个数是...的数有多少个” ,然后就是用组合数算在多少位里选几个1. ...

  4. 前端上传图片 base64转二进制上传

    var dataURItoBlob = function (dataURI) { var byteString = atob(dataURI.split(',')[1]); var mimeStrin ...

  5. 浅谈数位DP

    在了解数位dp之前,先来看一个问题: 例1.求a~b中不包含49的数的个数. 0 < a.b < 2*10^9 注意到n的数据范围非常大,暴力求解是不可能的,考虑dp,如果直接记录下数字, ...

  6. BZOJ3329 Xorequ(数位DP)

    题目大意:x xor 2x=3x(与x xor 3x=2x等价)求满足等式且小于n的x的个数,与满足等式小于2n的数的个数. 因为异或是不进位的二进制加法,那么因为结果正好和加法相同,那么说明x在二进 ...

  7. BZOJ 4513: [Sdoi2016]储能表 [数位DP !]

    4513: [Sdoi2016]储能表 题意:求\[ \sum_{i=0}^{n-1}\sum_{j=0}^{m-1} max((i\oplus j)-k,0) \] 写出来好开心啊...虽然思路不完 ...

  8. 【数位DP】题集

    1.[HDOJ2089] 题意:求区间内不出现4和62的数的个数 解法:模板题 2.[HDOJ3555] 题意:求区间内不出现49的数的个数 解法:模板题 3.[HDOJ5179] 题意:对于一个十进 ...

  9. 蒟蒻的数位DP专题总结

    BZOJ  1026: [SCOI2009]windy数: 题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1026           d ...

随机推荐

  1. Maven学习存档(1)——安装

    一.安装 1.1 jdk的下载与安装 下载地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html 版本:maven2 ...

  2. python基础知识0-4

    collection 他是对字典 元组 集合 进行加工的  是计数器 无论 深 ,浅 ,赋值 拷贝 内存地址都不变 赋值也是拷贝的一种 拷贝分两类数字 字符串 另一类: 列表 字典 元组 这一类还分两 ...

  3. Pytest+allure安装和框架搭建

    接口自动化框架搭建 -- 公司系统自测使用,只跑核心业务流程 编辑中...... 1.安装Pytest pip install -U pytest 1.1Pycharm测试脚本运行 创建project ...

  4. 22 Years of KDE

    22 Years of KDEhttps://timeline.kde.org/ http://www.kdedevelopers.org/

  5. url请求

    --[[local g = require 'library.global'--__ml_ss = mlc.prefix.ml_psession..tostring(os.time());local ...

  6. 作业7:常用java命令(一)

    一.Javac(java compiler) 1.功能:javac是一种前端编译器,负责将源代码转换为字节码. 2.例子 (1)代码 public class TestJavac { static c ...

  7. (三)创建基于maven的javaFX+springboot项目创建

    创建基于maven的javaFx+springboot项目有两种方式,第一种为通过非编码的方式来设计UI集成springboot:第二种为分离用户界面(UI)和后端逻辑集成springboot,其中用 ...

  8. 使用spring的test时,当配置文件不在classpath下,而在WEB-INF下

    @ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/applicationContext.xml"})

  9. vue的使用与安装 npm -v报错

    1.先将node从官方文档下载下来,然后进行安装. 安装成功后,在dos命令中node -v.npm -v来测试,如果成功就可以安装cnpm(国内淘宝镜像比较快).这里我遇到一个bug,npm -v压 ...

  10. 【Git的基本操作四】永久删除文件后找回

    永久删除文件后找回 1. 已经添加到本地库的文件 使用 reset 命令回退到未删除的历史记录即可 2.添加到缓存区,没有提交到本地库的文件找回 git reset --hard HEAD 命令即可找 ...