当前位置: 首页 > news >正文

动态规划篇(数位统计DP)

一、计数问题

 

#include <iostream>
#include <vector>

using namespace std;

int get(vector<int> num , int l , int r)
{
    int res = 0;
    for(int i = l ; i >= r ; i--)
        res = res * 10 + num[i];

    return res;
}

int power10(int x)
{
    int res = 1;
    while(x--)
        res *= 10;
    return res;
}

int count(int n , int x)
{
    if(!n) return 0;

    vector<int> num;
    while(n)
    {
        num.push_back(n % 10);
        n /= 10;
    }

    n = num.size();
    int res = 0;
    for(int i = n - 1 - !x ; i >= 0 ; i--)
    {
        if(i < n - 1)//当计算最高为时,不存在第一种情况①
        {
            res += get(num , n - 1 , i + 1) * power10(i);
            if(!x) res -= power10(i);//如果找的数是0,则不存在前导全零的情况,要减掉1种状况
        }
        if(num[i] > x) res += power10(i);
        else if(num[i] == x) res += get(num , i - 1 , 0) + 1;
    }
    return res;
}

int main()
{
    int n , m;
    while(cin >> n >> m , n || m)
    {
        if(n > m) swap(n , m);
        for(int i = 0 ; i <= 9 ; i++)
            cout << count(m , i) - count(n - 1 , i) << ' ';
        cout << endl;
    }
    return 0;
}

 

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std;


vector<int> dp(int n)
{
    vector<int> res(10, 0);
    if(!n) return res;

    vector<int> nums, last(10, 0);
    while (n) 
    {
        nums.push_back(n % 10);
        n /= 10;
    }

    //先求出位数在[1,nums.size()-1]之间的数中各位数的个数
    int len = nums.size() - 1;
    for (int i = 1; i < 10; i++) res[i] = len * pow(10, len - 1);
    if(len == 1) res[0] = 0;
    else if(len == 2) res[0] = 9;
    else
    {
        string t(len, '0');
        t[0] = '9';
        t[len - 1] = '1' + len - 3;
        for (int i = 1; i < len - 1; i++) t[i] = '8';
        reverse(t.begin(), t.end());
        res[0] = atoi(t.c_str()); 
    } 

    //求出位数为nums.size()的数中各位数的个数
    for (int i = nums.size() - 1; i >= 0; i--)
    {
        int x = nums[i];

        for (int j = i == nums.size() - 1; j < x; j++)
        {
            res[j] += pow(10, i);//j出现的个数
            for (int k = 0; k < 10; k++)
            {
                res[k] += last[k] * pow(10, i);//前缀中各位数出现次数
                res[k] += pow(10, i - 1) * i;//后缀中各位数出现次数
            }
        }
        last[x]++;//累计前缀

        //原数中每个数出现的次数也要累加进去(最右叶子节点)
        if(!i)
            for (int k = 0; k < 10; k++) res[k] += last[k]; 
    }

    return res;
}
int main()
{ 
    int a, b;
    while (cin >> a >> b ,  a | b)
    {
        if(a > b) swap(a, b);
        vector<int> v1 = dp(a - 1);
        vector<int> v2 = dp(b);

        for (int i = 0; i < 10; i++)
            cout << v2[i] - v1[i] << ' ';
        cout << endl;
    }
}

http://www.dtcms.com/a/99181.html

相关文章:

  • 用空闲时间做了一个小程序-二维码生成器
  • 【安全】nginx防止host头攻击
  • c++弱指针实现原理
  • Python小练习系列 Vol.5:数独求解(经典回溯 + 剪枝)
  • Linux之基础知识
  • 深度学习处理时间序列(5)
  • 《新凯来:半导体设备制造领域的“国家队”》
  • 【愚公系列】《高效使用DeepSeek》039-政务工作辅助
  • LeetCode 2360.图中的最长环:一步一打卡(不撞南墙不回头) - 通过故事讲道理
  • Redis延时队列在订单超时未报到场景的应用分享
  • 【数据结构】二叉树 — 经典OJ面试题剖析!!!
  • 关于 websocket协议的理解
  • 001 - 前缀和算法:从原理到实战,一文讲透区间和问题
  • 谈谈Minor GC、Major GC和Full GC
  • Java——数组
  • RSA 简介及 C# 和 js 实现【加密知多少系列_4】
  • .NET开发基础知识11-20
  • Lavazza拉瓦萨亮相上海樱花节,增色海派咖啡风情
  • rbpf虚拟机-汇编和反汇编器
  • OpenCV、YOLO与大模型的区别与关系
  • Web开发:数据的加密和解密
  • Python之函数
  • 图片RGBA像素值提取工具v1.0.0发布
  • 【原理系列】计算机组成原理-第一遍阅读总结
  • Flutter_学习记录_AppBar中取消leading的占位展示
  • Python:日志模块操作及基本配置,日志格式化输出
  • Mybatis源码 插件机制
  • Vue3 项目通过 docxtemplater 插件动态渲染 .docx 文档(带图片)预览,并导出
  • 人工智能与软件工程结合的发展趋势
  • 一些常用开发软件下载地址