洛谷 P6218 [USACO06NOV] Round Numbers S
洛谷 P6218 [USACO06NOV] Round Numbers S
题目描述
如果一个正整数的二进制表示中,\(0\) 的数目不小于 \(1\) 的数目,那么它就被称为「圆数」。
例如,\(9\) 的二进制表示为 \(10011001\),其中有 \(2\) 个 \(0\) 与 \(2\) 个 \(1\)。因此,\(9\) 是一个「圆数」。
请你计算,区间 \([l,r]\) 中有多少个「圆数」。
输入格式
一行,两个整数 \(l,r\)。
输出格式
一行,一个整数,表示区间 \([l,r]\)中「圆数」的个数。
输入输出样例
输入 #1
2 12
输出 #1
6
说明/提示
【数据范围】
对于 \(100\%\) 的数据,\(1\le l,r\le 2\times 10^9\)。
【样例说明】
区间 \([2,12]\) 中共有 \(6\) 个「圆数」,分别为 \(2,4,8,9,10,12\)
分析
比较套路的数位 \(DP\)
数位 \(DP\) 的实质就是换一种暴力枚举的方式,使得新的枚举方式满足 \(DP\) 的性质,然后记忆化就可以了。
首先,我们要进行 \(DP\) 的话,肯定要定义一个 \(f\) 数组存储我们计算过的值
因为这道题和数位有关,所以第一位我们要定义当前遍历到了第几位
而且我们还要判断二进制下 \(0\) 的数量和 \(1\) 的数量
所以,我们设 \(f[i][j][k]\) 为当前遍历到第 \(i\) 位,二进制下 \(1\) 的数量为 \(j\),\(0\) 的数量为 \(j\) 的数的个数
主函数我们用差分的思想搞一下即可
signed main(){
memset(f,-1,sizeof(f));
int l,r;
scanf("%lld%lld",&l,&r);
printf("%lld\n",solve(r)-solve(l-1));
return 0;
}
然后是 \(solve\) 函数
这里的 \(cnt\) 是用来记录当前的数在二进制下有多少位,\(num\) 数组是用来记录这个数每一二进制位上的数字的
这个函数的变量只有一个 \(xx\), 返回值是 \(0\) 到 \(xx\) 之间圆数的个数
int solve(int xx){
memset(num,0,sizeof(num));
cnt=0;
while(xx){
num[++cnt]=xx&1ll;
xx>>=1ll;
}
return dfs(cnt,0,0,1,1);
}
下面的 \(dfs\) 函数是最重要的部分
int dfs(int ws,int tot1,int tot0,bool lim,bool zer){
if(ws==0) {
if(tot1<=tot0) return 1;
return 0;
}
if(lim==0 && zer==0 && f[ws][tot1][tot0]!=-1) return f[ws][tot1][tot0];
int up=1,ans=0;
if(lim) up=num[ws];
for(int i=0;i<=up;i++){
if(zer==1 && i==0) ans+=dfs(ws-1,0,0,lim && i==up,1);
else ans+=dfs(ws-1,tot1+(i==1),tot0+(i==0),lim && i==up,0);
}
if(lim==0 && zer==0)f[ws][tot1][tot0]=ans;
return ans;
}
它的五个参数分别为:当前处理到第 \(ws\) 位
\(0\) 的个数 \(tot0\) ,\(1\) 的个数 \(tot1\)
\(lim\) 特判前一位是否为范围内的最大值
\(zer\) 记录有没有前导零
终止条件就是处理到最后一位
具体的边界看一下下面的模板
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int f[60][60][60],num[55],cnt,sum[55];
const int mod=1e7+7;
int dfs(int ws,int tot1,int tot0,bool lim,bool zer){
if(ws==0) {
if(tot1<=tot0) return 1;
return 0;
}
if(lim==0 && zer==0 && f[ws][tot1][tot0]!=-1) return f[ws][tot1][tot0];
int up=1,ans=0;
if(lim) up=num[ws];
for(int i=0;i<=up;i++){
if(zer==1 && i==0) ans+=dfs(ws-1,0,0,lim && i==up,1);
else ans+=dfs(ws-1,tot1+(i==1),tot0+(i==0),lim && i==up,0);
}
if(lim==0 && zer==0)f[ws][tot1][tot0]=ans;
return ans;
}
int solve(int xx){
memset(num,0,sizeof(num));
cnt=0;
while(xx){
num[++cnt]=xx&1ll;
xx>>=1ll;
}
return dfs(cnt,0,0,1,1);
}
signed main(){
memset(f,-1,sizeof(f));
int l,r;
scanf("%lld%lld",&l,&r);
printf("%lld\n",solve(r)-solve(l-1));
return 0;
}
洛谷 P6218 [USACO06NOV] Round Numbers S的更多相关文章
- 【题解】P6218 [USACO06NOV] Round Numbers S
题目传送门 这是一道数位DP. 令 \(dp_{i,j,k}\) 为满足由 \(i\) 位组成,且其中有 \(j\) 个1,第 i 位(从右往左数)为 \(k\) 的二进制数的数量. 可以得出状态转移 ...
- 洛谷P1879 [USACO06NOV]玉米田Corn Fields(状压dp)
洛谷P1879 [USACO06NOV]玉米田Corn Fields \(f[i][j]\) 表示前 \(i\) 行且第 \(i\) 行状态为 \(j\) 的方案总数.\(j\) 的大小为 \(0 \ ...
- 洛谷P2866 [USACO06NOV]糟糕的一天Bad Hair Day
P2866 [USACO06NOV]糟糕的一天Bad Hair Day 75通过 153提交 题目提供者洛谷OnlineJudge 标签USACO2006云端 难度普及/提高- 时空限制1s / 12 ...
- 【题解】洛谷P1879 [USACO06NOV] Corn Fields(状压DP)
洛谷P1879:https://www.luogu.org/problemnew/show/P1879 思路 把题目翻译成人话 在n*m的棋盘 每个格子不是0就是1 1表示可以种 0表示不能种 相邻的 ...
- 洛谷P1467 循环数 Runaround Numbers
P1467 循环数 Runaround Numbers 89通过 233提交 题目提供者该用户不存在 标签USACO 难度普及/提高- 提交 讨论 题解 最新讨论 暂时没有讨论 题目描述 循环数是 ...
- 洛谷 P1879 [USACO06NOV]玉米田 解题报告
P1879 [USACO06NOV]玉米田Corn Fields 题目描述 农场主\(John\)新买了一块长方形的新牧场,这块牧场被划分成\(M\)行\(N\)列\((1 ≤ M ≤ 12; 1 ≤ ...
- 洛谷P2867 [USACO06NOV]大广场Big Square
P2867 [USACO06NOV]大广场Big Square 题目描述 Farmer John's cows have entered into a competition with Farmer ...
- 洛谷——P2865 [USACO06NOV]路障Roadblocks
P2865 [USACO06NOV]路障Roadblocks 题目描述 Bessie has moved to a small farm and sometimes enjoys returning ...
- 洛谷 P2867 [USACO06NOV]大广场Big Square
P2867 [USACO06NOV]大广场Big Square 题目描述 Farmer John's cows have entered into a competition with Farmer ...
随机推荐
- luoguP1036 选数 暴力AC题解
luoguP1036 选数 暴力AC题解(非正解) 俗话说得好:暴力出奇迹,打表拿省一. 对于一些暴力就能拿分的题,暴力就好啦QWQ 题目描述 输入格式 输出格式 输入输出样例 定义变量 我们令输 ...
- pandas_学习的时候总会忘了的知识点
对Series 对象使用匿名函数 使用 pipe 函数对 Series 对象使用 匿名函数 pd.Series(range(5)).pipe(lambda x,y,z :(x**y)%z,2,5) p ...
- PHP array_combine() 函数
------------恢复内容开始------------ 实例 通过合并两个数组来创建一个新数组,其中的一个数组元素为键名,另一个数组元素为键值: <?php$fname=array(&qu ...
- C/C++编程笔记:C语言打造中国象棋游戏,项目源代码分享!
中国象棋是起源于中国的一种棋,属于二人对抗性游戏的一种,在中国有着悠久的历史.由于用具简单,趣味性强,成为流行极为广泛的棋艺活动. 它是中国棋文化,也是中华民族的文化瑰宝,它源远流长,趣味浓厚,基本规 ...
- 一个轻量级的基于RateLimiter的分布式限流实现
上篇文章(限流算法与Guava RateLimiter解析)对常用的限流算法及Google Guava基于令牌桶算法的实现RateLimiter进行了介绍.RateLimiter通过线程锁控制同步,只 ...
- 记录一次线上实施snmp
公司要实施一个部级的项目,我们公司的提供的产品要对接下客户的一个平台监控平台,该监控平台使用snmp,我们公司的产品不支持snmp,所以由我负责在现网实施snmp,记录这次现网 一.生成编译规则 1. ...
- 区块链钱包开发 - USDT - 一、Omni本地钱包安装
背景 Tether(USDT)中文又叫泰达币,是一种加密货币,是Tether公司推出的基于稳定价值货币美元(USD)的代币Tether USD,也是目前数字货币中最稳定的币,USDT目前发行了两种代币 ...
- [转]为什么阿里巴巴要禁用Executors创建线程池?
作者:何甜甜在吗 链接:https://juejin.im/post/5dc41c165188257bad4d9e69 来源:掘金 看阿里巴巴开发手册并发编程这块有一条:线程池不允许使用Executo ...
- 【SDOI2010】猪国杀 题解(模拟)
前言:嗅到了一丝头秃的味道…… ------------------ 题目链接 题目实在太长,变量也很多.建议至少读个三五遍再做题.不要忽略任何细节,不要想当然.(因为真正玩三国杀肯定不像猪一样出牌啊 ...
- 3月28日考试 题解(二分答案+树形DP+数学(高精))
前言:考试挂了很多分,难受…… --------------------- T1:防御 题意简述:给一条长度为$n$的序列,第$i$个数的值为$a[i]$.现让你将序列分成$m$段,且让和最小的一段尽 ...