The Counting Problem

询问区间\([a,b]\)中\(1\sim 9\)出现的次数,0 < a, b < 100000000。

显然为数位递推,考虑试填法,现在关键是求出方案数,于是设\(A[i]\)表示i位以内数字中0出现的次数,不含前导0,\(B[i]\)为i位数字中\(0\sim 9\)出现的次数,可以含前导0,不难有(其中\(base[i]=10^i\)),显然有

\[B[i]=10\times B[i-1]+base[i-1]
\]

\[A[i]=A[i-1]+9B[i-1]
\]

边界:\(A[0]=B[0]=0\)

解释:对于\(B[i]\),显然与第i位填什么有关,只能填0~9(含前导0),i-1位能够统计的数字个数翻10倍,然后对于第i位填上该个数字,剩下的数字自由组合有\(base[i-1]\),对于\(A[i]\),i-1位以内方案\(A[i-1]\),i位的方案是\(9B[i-1]\)(只能填\(1\sim 9\))。

于是对于一个数位题目,当我们处理好含前导0i位数字方案(前面的数字已经填好统计方案)和不含前导0i位以内的方案(前面的数字没有填好,不允许含前导0)的方程时,该题基本完成一半,罗嗦几句,帮助理解,对于\(1\sim 9\)的数字而言只需要\(B[i]\)数组即可,因为含前导0有两重意思都是等价的,一是i位数字上的含前导0的数的数字出现次数,二是i位以内的不含前导0的数的出现的次数,而0没有这个特殊待遇,于是得在维护一个\(A[i]\),剩下的照数位递推套路进行即可。

参考代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #define il inline
  5. #define ri register
  6. #define ll long long
  7. #define swap(x,y) x^=y^=x^=y
  8. using namespace std;
  9. int num[9];
  10. ll A[9],B[9],base[9],at[10],bt[10];
  11. il void prepare();
  12. il void ask(int n,ll[]);
  13. int main(){
  14. int a,b;prepare();
  15. while(scanf("%d%d",&a,&b),a&&b){
  16. if(a>b)swap(a,b);
  17. ask(a-1,at),ask(b,bt);
  18. for(int i(0);i<10;++i)
  19. printf("%lld ",bt[i]-at[i]);
  20. putchar('\n');
  21. }
  22. return 0;
  23. }
  24. il void ask(int n,ll ans[]){++n,num[0]&=0;
  25. do num[++num[0]]=n%10,n/=10;while(n);
  26. ans[0]=0;
  27. for(int j(num[0]),k,l(0);j;--j){
  28. for(k=0;k<num[j];++k)
  29. ans[0]+=A[j-1]+base[j-1]*(l+!k);
  30. if(!num[j])++l;
  31. }ans[0]+=B[num[0]-1],ans[0]-=A[num[0]-1]+base[num[0]-1];
  32. if(num[0]==1)++ans[0];
  33. for(int i(1),j,k,l;i<10;++i)
  34. for(j=num[0],l=ans[i]=0;j;--j){
  35. for(k=0;k<num[j];++k){
  36. ans[i]+=A[j-1]+base[j-1]*(l+(k==i));
  37. }if(num[j]==i)++l;
  38. }
  39. }
  40. il void prepare(){base[0]=1;
  41. for(int i(1);i<9;++i)
  42. base[i]=base[i-1]*10,A[i]=A[i-1]*10+base[i-1];B[1]=1;
  43. for(int i(2);i<9;++i)B[i]=9*A[i-1]+B[i-1];
  44. }

The Counting Problem的更多相关文章

  1. UVA 1640 The Counting Problem UVA1640 求[a,b]或者[b,a]区间内0~9在里面各个数的数位上出现的总次数。

    /** 题目:UVA 1640 The Counting Problem UVA1640 链接:https://vjudge.net/problem/UVA-1640 题意:求[a,b]或者[b,a] ...

  2. 『The Counting Problem 数位dp』

    The Counting Problem Description 求 [L,R]内每个数码出现的次数. Input Format 若干行,一行两个正整数 L 和 R. 最后一行 L=R=0,表示输入结 ...

  3. POJ2282 The Counting Problem

    题意 Language:DefaultEspañol The Counting Problem Time Limit: 3000MS Memory Limit: 65536K Total Submis ...

  4. UVa 1640 - The Counting Problem(数论)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  5. UVA 1640 The Counting Problem

    https://vjudge.net/problem/UVA-1640 题意:统计区间[l,r]中0——9的出现次数 数位DP 注意删除前导0 #include<cmath> #inclu ...

  6. [POJ 2282] The Counting Problem

    [题目链接] http://poj.org/problem?id=2282 [算法] 数位DP [代码] #include <algorithm> #include <bitset& ...

  7. POJ2282:The Counting Problem(数位DP)

    Description Given two integers a and b, we write the numbers between a and b, inclusive, in a list. ...

  8. UVa 1640 (计数) The Counting Problem

    题意: 统计[a, b]或[b, a]中0~9这些数字各出现多少次. 分析: 这道题可以和UVa 11361比较来看. 同样是利用这样一个“模板”,进行区间的分块,加速运算. 因为这里没有前导0,所以 ...

  9. UVa 1640 The Counting Problem (数学,区间计数)

    题意:给定两个数m, n,求从 m 到 n 中0-9数字各出现了多少次. 析:看起来挺简单的,其实并不好做,因为有容易想乱了.主要思路应该是这样的,分区间计数,先从个位进行计,一步一步的计算过来.都从 ...

随机推荐

  1. 如何设置linux启动过程中的停止阶段

    设置方法: 1 启动过程中点击“e”键(fedora)或者"tab"(centOS)键进入目标启动项的命令行参数下,移除initrd所在行末尾的"quiet" ...

  2. Quartz CronTrigger 整配置说明

    Quartz cron 表达式的格式向下支持到秒级别的计划,而 UNIX cron 计划仅支持至分钟级.  Quartz用cron 表达式存放执行计划,引用了cron表达式的CronTrigger在计 ...

  3. 在vue中获取不到canvas对象? 两种解决办法。

    1. mounted 钩子函数 初次肯定获取到id 2. 如果canvas父级用到了v-if 请改成v-show ,vue Dom节点 重新渲染导致methods 方法获取不到对象.

  4. pytest-mark跳过

    import pytestimport sysenvironment='android' @pytest.mark.skipif(environment=="android",re ...

  5. 并发编程 --进、线程池、协程、IO模型

    内容目录: 1.socket服务端实现并发 2.进程池,线程池 3.协程 4.IO模型 1.socket服务端实现并发 # 客户端: import socket client = socket.soc ...

  6. Centos Apache 80 代理Tomcat 8080端口

    运行环境:Centos 6.5 Apache: 2.2.5 开启apache proxy的相应模块 编辑 /etc/httpd/conf/httpd.conf文件 sudo vim /etc/http ...

  7. 【Bootstrap】 框架 栅格布局系统设计原理

    前提条件(Bootstrap 自带) 首先使用这个布局之前要定义一下代码: 这行代码如果不懂,可以搜索一下,总之大致意思就是,被定义的元素的内边距和边框不再会增加它的宽度,不加入的话排版会有问题. 不 ...

  8. Java中配置环境变量

    在系统环境变量中设置: ClASSPATH中输入: ".;C:\Program Files\Java\jdk1.7.0_07\jre\lib\rt.jar;"//java的安装目录 ...

  9. NX二次开发-创建图纸尺寸表达式抑制UF_DRF_add_controlling_exp

    #include <uf.h> #include <uf_modl.h> #include <uf_drf.h> #include <uf_obj.h> ...

  10. C++ 将汉字转换成拼音全拼【转载】

    转载自https://www.cnblogs.com/mzhrd/p/4758105.html #include <string> using std::string; //======= ...