zoukankan      html  css  js  c++  java
  • 14.计数问题 数位统计DP --------------------------待复习标志--------------------------

     

     

     不要问我经历了什么,这道题目我卡了三分之一天 

    三分之一天的时间在看这道题目

    这道题目是一个大综合,涉及到新知识数位统计DP,以及前缀和,还有字符串操作,而且细节巨多

    蓝桥杯里类似的题目是给定两个数a和b(都是500以内),问[a,b]区间里所有整数中1出现的总次数。

    然后看看这一题,

    100000000

    还是多组测试样例

    还要统计0~9每个数的出现次数

    暴力做法死无全尸,也就是我的死法

    数位统计DP主要涉及小学数奥的知识,没错,小学。但是我不会。

    主要思路就是:分情况讨论。

    整这道题时,一半时间在想这个小学数奥,剩下一半时间花在代码实现的细节处理上

    接下来,小学数奥来了。

    情况一:当我们要统计的数x大于零时

    情况二:当我们要统计的数x等于零时

    那么我们分类时的情况①就会出现前导0的问题

     所以就需要从001开始枚举

    然后就是整了三分之一天,然后AC的代码

    细节巨多

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 /*
     4 001~abc-1, 999
     5 abc
     6     1. num[i] < x, 0
     7     2. num[i] == x, 0~efg
     8     3. num[i] > x, 0~999
     9 */
    10 int get(vector<int> &num, int l, int r) { //求前面这个数字是多少
    11     //从第l位到r位
    12     int res = 0;
    13     for (int i = l; i >= r; i--) {
    14         res = res * 10 + num[i];
    15     }
    16     return res;
    17 }
    18 int power10(int x) { //求10的x次方
    19     int res = 1;
    20     while (x--) {
    21         res *= 10;
    22     }
    23     return res;
    24 }
    25 int count(int n, int x) { 
    26     //这个函数返回区间[1, n]的所有整数中,数字x出现的总次数
    27     //数字x的取值范围是0~9
    28     if (!n) { //边界条件,因为是统计区间[1, n],所以n = 0时直接没有
    29         return 0;
    30     }
    31     vector<int> num; //把当前数字的每一位都抠出来
    32     while (n) { //抠数字操作
    33         num.push_back(n % 10);
    34         n /= 10;
    35     }
    36     n = num.size(); //然后让n = n的位数
    37     int res = 0; //答案
    38     //当x等于0时,从第二位开始枚举
    39     for (int i = n - 1 - !x; i >= 0; i--) { //从最高位开始枚举,注意是倒着来的
    40         if (i < n - 1) { //情况①,不是最高位时才存在
    41             res += get(num, n - 1, i + 1) * power10(i);
    42             //从n - 1到i + 1     乘以     10的i次方
    43             //res += 
    44             //我们枚举到的这一位前面的数字 乘以 10的这一位后面的位数次方
    45             if (!x) { //当x = 0 时
    46                 res -= power10(i);
    47             }
    48         }
    49         if (num[i] == x) { //情况②的2
    50             res += get(num, i - 1, 0) + 1;
    51         } else if (num[i] > x) { //情况②的3
    52             res += power10(i);
    53         }
    54     }
    55     return res; //返回答案
    56 }
    57 int main() {
    58     int a, b;
    59     while (cin >> a >> b && a != 0) { //实现【循环读入多组数据,且读到0, 0时就停止】这一功能
    60         if (a > b) { //因为要求区间[a, b],所以一定要保证a <= b
    61             swap(a, b);
    62         }
    63         for (int i = 0; i <= 9; i++) {
    64             cout << count(b, i) - count(a - 1, i) << " "; //前缀和思想
    65         }
    66         cout << endl;
    67     }
    68     return 0;
    69 }

    题目出处

    算法竞赛进阶指南这本书还没有开始刷,就是这本

     这道题目的难度一言难尽

    先看下这道题目视频讲解的时长

     你没看错,这道题目讲解了1小时13分钟,虽然中间小小翻车一次

    然后半小时讲小学数奥,半小时debug代码

    以前做题听讲解,1.5倍速轻松无压力

    这道题目,全程一倍速,完全不敢加速

    到处是细节,还要不停的后退反复听

    这道题目的思路解析我写的很少,吃了没学小学数奥的亏

    实在是用文字解释不出来

    然后看了看大佬们的解析

    然后这位大佬是谁呢

     算法竞赛进阶指南总题目328道,解决252道,排名第10

     然后就是强行安慰自己了,虽然我没学过小学数奥

    但是大佬用了一个晚上,按照一天 = 白天 + 晚上来看的话

    一个晚上 = 1 / 2 * 一天 = 24小时 / 2 = 12小时

    所以强行安慰自己花了三分之一天还是可以接受的

    然后到这里,本题就已经结束了,再往下就是做这道题目时的心路历程了

    ======================说废话用分割线======================

    其实吧,做这道题时真的好艰难

    然后之前写的课程设计报告格式还不对,昨天还被文化课老师批了一顿

    然后第一次怀疑自己了,为什么要花时间打ACM

    安稳得去学文化课不香吗,所有时间去整文化课,然后各种被老师夸不好吗

    老师们又不会看我学算法然后考试时给我加上几分

    作业老师们也不会额外加时,让我多点时间去做

    作业截止没提交就扣分,作业写的不好还是会批评

    要打ACM就需要在保证文化课绩点的同时,自己额外抽出时间刷题

    绩点和竞赛不可兼得,总有一样会变弱

    想了想我的算法入门经历

    up主在2019年10月接触算法

    2019年10月在牛客上AC了人生中的第一道题目

    签到难度的Hello World

    第一次打比赛,罚时一天

    到现在历时10个月

    蓝桥杯刷题360道

     洛谷刷题202道

    牛客累计打比赛24场

     博客园累计写博客155篇

     真的是第一次犹豫要不要继续了

    然后然后,就是一边怀疑人生,一边听着这一个小时的视频讲解

    一边骂着数奥滚粗,一边改着代码

    然后在点击提交显示AC之后

     没错,我就是爱ACM,我享受AC题目的快感

    既入此道,落子无悔

    身为预备队二队队长

    实力服众才有领导力

     队长就要有队长的担当,毕竟要拿实力证明自己不是废物

    时间还有一周,二队快要迎来首战了

    该给队友加训了

                                             ----------2020年7月5日凌晨4点博客园有感

    ==========2020年8月17日更新==========

    二队已经被淘汰除名,再也不能以二队自居了

  • 相关阅读:
    Linux之Ubuntu添加/移除个人软件包存档的源[PPA,Personal Package Archives]
    [C++]Linux之头文件sys/types.h[/usr/include/sys]
    [C++]Linux之文件拷贝在系统调用和C库函数下的效率比较
    Linux之Ubuntu下安装屏幕录像软件(SimpleScreenRecorder)【摘抄】
    [C++]基于Curses库的实时系统监测可视化系统-2017-12-09 15-07-42
    [C++]Linux之虚拟文件系统[/proc]中关于CPU/内存/网络/内核等的一些概要性说明
    [C++]Linux之计算内存利用率与辨析
    [C++]Linux之网络实时检测功能
    [C++]Linux之C编程异常[true未定义解决方案]
    [C++]Linux之读取计算机网络数据[/proc/net/dev]
  • 原文地址:https://www.cnblogs.com/fx1998/p/13237505.html
Copyright © 2011-2022 走看看