The page number of a book is encoded from the natural number 1 in order until the natural number N. The pages of the book are arranged in the usual way, with no extra leading digits of 0 per page. For example, page 6th is represented by 6 instead of 06 or 006. The problem of digital statistics requires the total number of pages in a given book, and how many digital 0,1,2,3 are used for each page number of the book,..... 9.
This topic has the most easily thought of N*LOG10 (n) algorithm. This is the code you wrote for the Complexity O (N*LOG10 (n)):
void Statnumber (int n) {
int i, t;
int count[10] = {0};
for (i = 1; I <= n; i++) {
t = i;
while (t) {
count[t%10]++;
t/=10
}
}
for (i = 0; i < i++) {
printf ("%d/n", Count[i]);
}
Carefully consider the characteristics of M n-bit decimal number, in a n-bit decimal number from low to high number I, always appear 10^i 0, then 10^i 1 ... Until the 10^i a 9,9 is a continuous 10^i 0, so the loop appears. By finding this rule, you can calculate the number of occurrences of each digit on the first digit in the constant time. On the first digit, the first 10^i 0 is a leading 0 and should be reduced.
In this way, you can only parse each digit of the given input integer n, and a log10 (n) algorithm can be obtained from the surface, and the code is as follows:
void Statnumber (int n) {
int m, I, J, K, T, x, len = log10 (n);
Char d[16];
int pow10[12] = {1}, count[10] = {0};
for (i = 1; i < i++) {
pow10[i] = pow10[i-1] *
sprintf (d, "%d", n);
m = n+1;
for (i = 0; I <= len; i++) {
x = d[i]-' 0 ';
t = (m-1)/pow10[len-i];
COUNT[X] + + m-t * Pow10[len-i];
T/=;
j = 0;
while (J <= x-1) {
Count[j] + = (t + 1) * Pow10[len-i];
j + +;
}
while (J < ten) {
count[j] + = t * pow10[len-i];
j + +;
}
Count[0]-= pow10[len-i]; /* The first digit 10^i 0 is meaningless
/} for
(j = 0; J <; j) {
printf ("%d/n", Count[j]);
}
By comparing the randomly generated test data, you can verify that the second piece of code is correct.
For two pieces of code to do efficiency testing, the first randomly generated 200,000 integers, the result on my computer, the second piece of code executes 1.744 seconds. The first paragraph of code when I finished eating the sheet back to see still no response, forcibly shut it.
The second time 1000 integers were generated and tested again, and the first piece of code executed on my computer was
10.144 seconds, and the second code executes 0.0800 seconds.
The reason is that the first paragraph of code time complexity is O (N*LOG10 (n)), the M input integer calculation, the time required for 1*LOG10 (1) + 2*LOG10 (2) + ... + m*log10 (m), when n > 10 o'clock, have
N*LOG10 (n) > N, so the lower bound of the upper type is 11+12+....+m, and its asymptotic boundary is m*m. For 200,000 test data, the lower bound of its running time is 4*10^10.
The second piece of code is N*LOG10 (n) for the run-time bounds of n input data.
The above code has a POW10 array to record the 10^i, but 10^10 is already over 2^32, but the range of input integers given by the topic is within 10^9, so it has no effect.
The analysis given in the original works is as follows:
Investigate all n digits composed of 0,1,2...9. from N 0 to N 9 a total of 10^n n digits. In this 10^n n-digit number, the 0,1,2.....9 number is used the same number of times, set to F (n). F (n) satisfies the following recursive type:
N>1:
F (n) = 10f (n-1) +10^ (n-1)
n = 1:
F (N) =1
So, f (n) = n*10^ (n-1).
According to this, can be from high to low to statistics, and then minus the extra 0 of the number can be.
The author's thoughts are more clearly said to be like this:
For an M-bit integer, we can arrange the n+1 integers between 0 and n from small to large:
000......0
.............
199......9
200......0
299......9
.........
This goes straight to the natural number N. For from 0 to 199 ... 9 in this range, the number of the highest digits does not look, its low m-1 bit happens
is the number of m-1 0 to M-1 9 10^ (m-1). Using the recursive formula in the original, in this interval, the number of occurrences of each number
(excluding the highest digits) is (m-1) *10^ (m-2). Assuming that the highest digit of n is x, then the interval mentioned above is common to n
X A. Then the number of times each number appears x times can be counted out of these intervals. And look at the highest digits of the situation, apparently 0 to x-1 these
The number of occurrences at the highest level is 10^ (m-1), because one interval length is 10^ (m-1). and the number of x at the highest level is
n%10^ (m-1) +1. Then repeat the above method for n%10^ (m-1), that is, to remove the number after the highest digit. Until
Bit, you can complete the question request.
For example, for a number 34567, we can calculate the number of occurrences of each digit in all numbers from 1 to 34567:
From 0 to 9999, the number of occurrences of each number in this interval can be calculated using the recursive formula given in the original, that is, 4,000 times per digit.
From 10000 to 19999, the middle to remove the million-digit 1 does not count, but also a from 0000 to 9999 arrangement, so that, from 0 to 34567
There are 3 such intervals. So from 00000 to 29999 apart from the million, each number appears for 3*4000 times. And then count it again.
million digits, each interval length of 10000, so 0,1,2 on the million appeared 10,000 times. and 3 appeared 4567+1=4568 times.
After that, throw away the million digits, for 4567, and then use the above method calculation, has been calculated to a single-digit.
Here's your implementation code:
void statnumber_iterative (int n) {
int len, I, K, H, M;
int count[10] = {0};
int pow10[12] = {1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};
Char d[16];
Len = log10 (n); /* Len indicates the current digit's bit right *
/m = len;
sprintf (d, "%d", n);
k = 0; /* k Records the subscript
/h = d[k]-' 0 ' of the current highest digits in the D array; /* H means the current highest number
/n%= Pow10[len]; /* Remove the highest bit of n
/while (len > 0) {
if (h = = 0) {
count[0] + = n + 1;
h = d[++k]-' 0 ';
--len;
n%= Pow10[len];
Continue;
}
for (i = 0; i < i++) {
Count[i] + = h * len * pow10[len-1];
}
for (i = 0; i < H; i++) {
Count[i] + = Pow10[len]
;
COUNT[H] + = n + 1;
--len;
h = d[++k]-' 0 ';
n%= Pow10[len];
}
for (i = 0; I <= h; i++) {
count[i] = 1;
}
/* Minus the number of leading 0 * for
(i = 0; I <= m i++) {
count[0] = Pow10[i];
}
for (i = 0; i < i++) {
printf ("%d/n", Count[i]);
}
The above is the entire content of this article, I hope to help you learn.