zoukankan      html  css  js  c++  java
  • 洛谷P6218 [USACO06NOV] Round Numbers S 题解 数位DP

    题目链接:https://www.luogu.com.cn/problem/P6218

    题目大意:
    ([l,r]) 范围内有多少数满足二进制表示中的 (0) 的数量大于等于 (1) 的数量。

    解题思路:
    数位DP,定义状态 (f[p][z][x]) 表示:

    • 当前在第 (p) 位;
    • (z) 对应目前是否一直是前置零(true为一直是,false为不是);
    • (x) 表示 (0) 的数量减去 (1) 的数量(因为在实现时可能存在 (x) 是负数所以实现的时候加了一个 (33) 的偏移)。

    示例程序如下:

    #include <bits/stdc++.h>
    using namespace std;
    // f[p][z][x]表示第p为,z=0个数-1个数,x
    int f[33][2][66], a[33], tmp;
    bool vis[33][2][66];
    int dfs(int p, bool z, int x, bool limit) {
        if (p == -1) {
            return x >= 0 ? 1 : 0;
        }
        if (!limit && vis[p][z][x+33]) return f[p][z][x+33];
        int res = 0, up = limit ? a[p] : 1;
        for (int i = 0; i <= up; i ++) {
            tmp += (1<<p) * i;
            bool zz = z && i==0 && p;
            int xx = x;
            if (i == 1) xx --;
            else if (!zz) xx ++;
            res += dfs(p-1, zz, xx, limit && i==up);
            tmp -= (1<<p) * i;
        }
        if (!limit) {
            vis[p][z][x+33] = true;
            f[p][z][x+33] = res;
        }
        return res;
    }
    int handle(int num) {
        int p = 0;
        while (num) {
            a[p++] = num % 2;
            num /= 2;
        }
        return dfs(p-1, true, 0, true);
    }
    int main() {
        int l, r;
        cin >> l >> r;
        cout << handle(r) - handle(l-1) << endl;
        return 0;
    }
    
  • 相关阅读:
    google浏览器切换成中文
    Python 进阶篇
    Linux 命令
    Linux
    Linux
    Linux
    Linux--shell脚本之文本处理工具
    Linux--shell脚本之正则表达式
    Linux
    Linux
  • 原文地址:https://www.cnblogs.com/quanjun/p/14550130.html
Copyright © 2011-2022 走看看