圆形数字

简介: 圆形数字

定义圆形数字如下:

把一个十进制数转换为一个无符号二进制数,若该二进制数中 0 的个数大于或等于 1 的个数,则它就是一个圆形数字。

现在给定两个正整数 a 和 b,请问在区间 [a,b] 内有多少个圆形数字。

输入格式
输入占一行,包含两个整数 a 和 b。

输出格式
输出一个整数,表示圆形数字的个数。

数据范围
1≤a<b≤2×109
输入样例:
2 12
输出样例:
6

题意:
把一个十进制数字转换为一个无符号二进制数,若该二进制中的0的个数大于等于1的个数,则为一个圆形数字。

给定整数a,ba,b,问区间a,b内有多少个圆形数字。

思路:
数位dp+记忆化搜索。

设f(pos,det)f(pos,det)表示处理到pospos位,当前detdet是多少的答案。

detdet是这个二进制数00的数量减去11的数量。

当然需要注意的是,11的数量可能大于00的数量导致detdet为负,所以我们加上一个3535作为基值。

同时要注意前导0的影响:

如果当前前导0标记为1且本位也是0,表示当前位也是前导0,pos+1继续搜索。

如果当前前导0标记为1但本位不是0,表示当前位为该次搜索的最高位。、

别忘了初始化dp数组,别问我为啥知道QwQ

#include<bits/stdc++.h>
using namespace std;
int a[40];
int f[40][70];

int dfs(int pos, int det, bool limit, bool lead)
{
    if(pos == 0) return det >= 35;
    if(!limit && !lead && f[pos][det] != -1) return f[pos][det];
    int up = limit?a[pos]:1;
    int ans = 0;
    for(int i = 0; i <= up; i++)
    {
        if(i==0 && lead) ans += dfs(pos-1, 35, limit&&(i==a[pos]), true);
        else if(i) ans += dfs(pos-1, det-1, limit&&(i==a[pos]), false);
        else ans += dfs(pos-1, det+1, limit&&(i==a[pos]), false);
    }
    if(!limit && !lead) f[pos][det] = ans;
    return ans;
}

int solve(int x)
{
    int len = 0;
    while(x)
    {
        a[++len] = x&1;
        x >>= 1;
    }
    return dfs(len, 35, 1, 1);
}

int main()
{
    memset(f, -1, sizeof(f));
    int l, r; scanf("%d%d", &l, &r);
    if(l > r) swap(l, r);
    cout << (solve(r)-solve(l-1))<<endl;
    return 0;
}

目录
相关文章
|
6月前
|
算法 C# C++
HOperatorSet.GenRectangle1 参数是负数的矩形
HOperatorSet.GenRectangle1 参数是负数的矩形
|
9天前
|
算法 测试技术 C#
【单调栈】【网格】【柱图面积】85. 最大矩形
【单调栈】【网格】【柱图面积】85. 最大矩形
|
4月前
|
机器人 C# 图形学
C# | [极坐标] 与 [平面直角系坐标] 的相互转换
极坐标和平面直角系坐标是常见的坐标系统,它们在不同的应用场景中都有重要的作用。而在计算机图形学、物理模拟和机器人控制等领域,我们经常需要在极坐标和平面直角系坐标之间进行转换。
60 2
C# | [极坐标] 与 [平面直角系坐标] 的相互转换
|
10月前
|
Python
Python|给定点到原点的螺旋折线(顺时针)长度
Python|给定点到原点的螺旋折线(顺时针)长度
50 0
|
11月前
给定圆的半径r,求圆的面积。
给定圆的半径r,求圆的面积。
F - 数字方格
image 如上图,有3个方格,每个方格里面都有一个整数a1,a2,a3。已知0 result?max:result; } } } } System.
895 0