整体思路:对于每一位,先将当前未达到$limit$部分的段 [如 $0$ ~ $10000$] 直接处理好,到下一位时再处理达到$limit$的部分。

· $1 × 10 ^ n$以内每个数(包括$0$)的出现次数的计算 [即已知$bitnum[n - 1]$,求$bitnum[n]$]: 将$bitnum[n - 1]$乘以$10$,代表$n - 1$处最为每个小段在$n$处出现$10$次,再加上$power10[n - 1]$,即加上新增的最高位该数出现次数。

· $1 × 10 ^ n$以内$0$的出现次数的计算 [即已知$bitzero[n - 1]$,求$bitzero[n]$]: 将$bitzero[n - 1] + power10[n - 2] - 1$ ··· ①,表示在$n - 1$的所有数($power10[n - 2] - 1$)个前都加上一个前导零,再将① $* 10$,表示该小段出现$10$次。

· 处理$limit$位: 首先保存前$n + 1$位的$limit$位,那么前$n + 1$位的$limit$为在当前第$n$位的贡献即它们在$0$ ~ $limit × 10 ^ n$中每一大段停留的次数,即 [它们的出现次数 × $power10[n - 1]$]。

· 处理非$limit$位: 直接加上$bitnum$或$bitzero$(前导零情况)即可。

· 代码:

 #include <iostream>
#include <cstdio>
#include <cstring> using namespace std; typedef long long LL; const int MAXN = + ;
const int MAXM = ; LL power10[MAXN]; LL bitnum[MAXN];
LL bitzero[MAXN]; void Preparation () {
power10[] = ;
for (int i = ; i <= MAXM; i ++)
power10[i] = power10[i - ] * ; bitnum[] = ;
for (int i = ; i <= MAXM; i ++)
bitnum[i] = bitnum[i - ] * + power10[i - ]; bitzero[] = , bitzero[] = ;
for (int i = ; i <= MAXM; i ++)
bitzero[i] = (bitzero[i - ] + power10[i - ] - ) * ;
} LL Answers[][MAXM]; int L, R; int bit[MAXN];
int N; int cobit[MAXN]; void separ (int p) {
memset (cobit, , sizeof (cobit)); if (! p)
cobit[] = ;
while (p) {
cobit[p % ] ++; p /= ;
}
} void Solve (int M, int type) {
if (M <= ) {
if (M == )
Answers[type][] = ; return ;
} int tmpM = M; N = ;
while (tmpM) {
bit[++ N] = tmpM % ; tmpM /= ;
} int bits = ; for (int i = N; i >= ; i --) {
bits *= ; for (int j = ; j < bit[i]; j ++) {
if (bits + j || i == ) { // 处理limit位
separ (bits + j); for (int k = ; k <= ; k ++)
Answers[type][k] += (LL) cobit[k] * power10[i - ];
} for (int k = ; k <= ; k ++)
Answers[type][k] += bitnum[i - ];
Answers[type][] += (bits + j ? bitnum[i - ] : bitzero[i - ]);
} bits += bit[i];
} separ (M); for (int k = ; k <= ; k ++)
Answers[type][k] += cobit[k];
} int main () {
Preparation (); while (~ scanf ("%d%d", & L, & R) && L + R) {
if (L > R)
swap (L, R); memset (Answers, , sizeof (Answers)); Solve (L - , );
Solve (R, ); for (int i = ; i <= ; i ++) {
if (i)
putchar (' '); printf ("%lld", Answers[][i] - Answers[][i]);
} puts ("");
} return ;
} /*
1 10
44 497
346 542
1199 1748
1496 1403
1004 503
1714 190
1317 854
1976 494
1001 1960
0 0
*/

POJ - Problem 2282 - The Counting Problem的更多相关文章

  1. [POJ 2282] The Counting Problem

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

  2. (Problem 73)Counting fractions in a range

    Consider the fraction, n/d, where n and d are positive integers. If nd and HCF(n,d)=1, it is called ...

  3. (Problem 72)Counting fractions

    Consider the fraction, n/d, where n and d are positive integers. If nd and HCF(n,d)=1, it is called ...

  4. 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] ...

  5. foj Problem 2282 Wand

     Problem 2282 Wand Accept: 432    Submit: 1537Time Limit: 1000 mSec    Memory Limit : 262144 KB Prob ...

  6. 尺取法 POJ 3320 Jessica's Reading Problem

    题目传送门 /* 尺取法:先求出不同知识点的总个数tot,然后以获得知识点的个数作为界限, 更新最小值 */ #include <cstdio> #include <cmath> ...

  7. POJ 3100 Root of the Problem || 1004 Financial Management 洪水!!!

    水两发去建模,晚饭吃跟没吃似的,吃完没感觉啊. ---------------------------分割线"水过....."--------------------------- ...

  8. 『The Counting Problem 数位dp』

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

  9. POJ2282 The Counting Problem

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

随机推荐

  1. Android四大组件之Intent

    Intent不是android几大组件框架,但是确实是android 各大组件之间沟通的桥梁. 尤其Intent对于activity有很大的关系. 一下是我个人对task以及backstack的总结.

  2. 洛谷 P4066 [SHOI2003]吃豆豆 解题报告

    P4066 [SHOI2003]吃豆豆 题目描述 两个PACMAN吃豆豆.一开始的时候,PACMAN都在坐标原点的左下方,豆豆都在右上方.PACMAN走到豆豆处就会吃掉它.PACMAN行走的路线很奇怪 ...

  3. Linux(三)高级文本处理命令

    一.cut (cut 命令可以从一个文本文件或者文本流中提取文本列 ) 1.cut语法 cut -d '分隔字符' -f fields         用于有特定分隔字符 cut  -c 字符区间   ...

  4. Linux之执行命令操作20170330

    介绍一下Linux系统中的代码执行shell等命令的几种操作方式: 一.标准流管道popen 该函数的原型是FILE * popen(const char* command, const char * ...

  5. Java配置jdk图文教程

    1.计算机 ==>右键属性 2.高级系统设置 3.环境变量 4.找path变量 5.找到jdk的bin目录并复制路径到path环境变量里(jdk5.0以后就可以只配path路径了). 6.pat ...

  6. selenium - 查看selenium版本信息

    1. pip list 2. pip show selenium 3. cmd>>python >>> import selenium>>> help( ...

  7. 【题解】Points, Lines and Ready-made Titles Codeforces 871C 图论

    Prelude 真是一道好题,然而比赛的时候花了太多时间在B题上,没时间想这个了QAQ. 题目链接:萌萌哒传送门(.^▽^) Solution 观察样例和样例解释,我们发现,假如有四个点,恰好占据在某 ...

  8. varchar字段

    varchar  最长26000多,实际使用最好不要超过255,会占内存 可以考虑text

  9. hibernate中evict()和clear()的区别

    session.evict(obj):会把指定的缓冲对象进行清除: session.clear():把缓冲区内的全部对象清除,但不包括操作中的对象. hibernate执行的顺序如下: (1)生成一个 ...

  10. spring boot 2.0.3+spring cloud (Finchley)4、熔断器Hystrix

    在分布式系统中服务与服务之间的依赖错综复杂,一种不可避免的情况就是某些服务会出现故障,导致依赖于他们的其他服务出现远程调度的线程阻塞.某个服务的单个点的请求故障会导致用户的请求处于阻塞状态,最终的结果 ...