POJ - Problem 2282 - The Counting Problem

整体思路:对于每一位,先将当前未达到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 */

猜你喜欢

转载自www.cnblogs.com/Colythme/p/9696555.html