POJ

整体思路:对于每一位,先将当前未达到$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$(前导零情况)即可。

· 代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 
  5 using namespace std;
  6 
  7 typedef long long LL;
  8 
  9 const int MAXN = 10 + 5;
 10 const int MAXM = 10;
 11 
 12 LL power10[MAXN];
 13 
 14 LL bitnum[MAXN];
 15 LL bitzero[MAXN];
 16 
 17 void Preparation () {
 18     power10[0] = 1;
 19     for (int i = 1; i <= MAXM; i ++)
 20         power10[i] = power10[i - 1] * 10;
 21 
 22     bitnum[0] = 0;
 23     for (int i = 1; i <= MAXM; i ++)
 24         bitnum[i] = bitnum[i - 1] * 10 + power10[i - 1];
 25 
 26     bitzero[0] = 0, bitzero[1] = 1;
 27     for (int i = 2; i <= MAXM; i ++)
 28         bitzero[i] = (bitzero[i - 1] + power10[i - 2] - 1) * 10;
 29 }
 30 
 31 LL Answers[2][MAXM];
 32 
 33 int L, R;
 34 
 35 int bit[MAXN];
 36 int N;
 37 
 38 int cobit[MAXN];
 39 
 40 void separ (int p) {
 41     memset (cobit, 0, sizeof (cobit));
 42 
 43     if (! p)
 44         cobit[0] = 1;
 45     while (p) {
 46         cobit[p % 10] ++;
 47 
 48         p /= 10;
 49     }
 50 }
 51 
 52 void Solve (int M, int type) {
 53     if (M <= 0) {
 54         if (M == 0)
 55             Answers[type][0] = 1;
 56 
 57         return ;
 58     }
 59 
 60     int tmpM = M;
 61 
 62     N = 0;
 63     while (tmpM) {
 64         bit[++ N] = tmpM % 10;
 65 
 66         tmpM /= 10;
 67     }
 68 
 69     int bits = 0;
 70 
 71     for (int i = N; i >= 1; i --) {
 72         bits *= 10;
 73 
 74         for (int j = 0; j < bit[i]; j ++) {
 75             if (bits + j || i == 1) { // 处理limit位
 76                 separ (bits + j);
 77 
 78                 for (int k = 0; k <= 9; k ++)
 79                     Answers[type][k] += (LL) cobit[k] * power10[i - 1];
 80             }
 81 
 82             for (int k = 1; k <= 9; k ++)
 83                 Answers[type][k] += bitnum[i - 1];
 84             Answers[type][0] += (bits + j ? bitnum[i - 1] : bitzero[i - 1]);
 85         }
 86 
 87         bits += bit[i];
 88     }
 89 
 90     separ (M);
 91 
 92     for (int k = 0; k <= 9; k ++)
 93         Answers[type][k] += cobit[k];
 94 }
 95 
 96 int main () {
 97     Preparation ();
 98 
 99     while (~ scanf ("%d%d", & L, & R) && L + R) {
100         if (L > R)
101             swap (L, R);
102 
103         memset (Answers, 0, sizeof (Answers)); 
104 
105         Solve (L - 1, 0);
106         Solve (R, 1);
107 
108         for (int i = 0; i <= 9; i ++) {
109             if (i)
110                 putchar (' ');
111 
112             printf ("%lld", Answers[1][i] - Answers[0][i]);
113         }
114 
115         puts ("");
116     }
117 
118     return 0;
119 }
120 
121 /*
122 1 10
123 44 497
124 346 542
125 1199 1748
126 1496 1403
127 1004 503
128 1714 190
129 1317 854
130 1976 494
131 1001 1960
132 0 0
133 */
View Code
原文地址:https://www.cnblogs.com/Colythme/p/9696555.html