The night before, a senior researcher suddenly ran to our dormitory and asked us a Microsoft exam. Give you an integer N and obtain the number of numbers 0 in the range of 1 to n. For example, when n = 10, only 10 contains 0, and 1 is output, if n is 90, 9 is output. The only requirement is that this question cannot be implemented through traversal. The time responsibility is smaller than O (N). If traversal is performed, it is obvious that everyone will do it.
Looking at this question at the beginning, it seems that we can find the law. It should be the idea of arrangement and combination. below is the idea provided by one of the students I know who want to learn mathematics:
The mathematical method seems to be able to solve the problem, but I didn't try it. After asking an ACM Daniel, I got the term "Digital DP" and found that there are many similar questions that can be solved using the digital DP Method.
The following describes the background of the digital DP:
• Find the number that meets the requirements within the given range [a, B. • The requirement is generally unrelated to the number size, but related to the composition of the number • For example, an incremental value of 1234,257... • Double peak... • 49-inclusive, 49,149,149 2... • 13, 26, 39... • The trouble is that the scale is large and the number of digits is greater than 100. Enumeration cannot be performed. • The interval is often not a whole hundred thousands, and the Boundary Problem • • Note -Clear memory Search Ideas -Open a proper space -Find the appropriate status to simplify the calculation workload
To reduce the time complexity, you can use the state transition in the traditional DP to create tables and obtain the digital DP:
F (a, B) = f (B, 0)-f (A-1, 0)
Brute force + storage = memory-based search
• Violence: • Each digit of the brute-force enumeration (0 .. 9), pay attention to the interval boundary, and match the symbol.
• DFS (I, j, k, flag) • Enumerate the number of I-bits, matching STR [J]. The first digit is K and whether it reaches the upper limit (flag = true, false) • If the upper limit is reached, only 0 .. num [I] can be enumerated. Otherwise, 0 .. 9 can be enumerated. • Storage • DFS (I, j, k, flag) • The Set state is consistent with the recursive parameter f [I] [J] [k] [flag], indicating that when the number of I-bits is enumerated, matching STR [J], the number of numbers that meet the requirements when the first digit is K and the threshold is reached (flag = true, false. • The DFS process is equivalent to filling F. Suppose f space O (100*10*10*2), then the DFS time O (20000)
For the above several types of problems, the digital DP Solution is as follows: (you can see the specific http://www.cppblog.com/Yuan/archive/2011/07/15/139299.html)
• Division 13 • DFS (I, m, flag) • enumeration of the I-digit number, the remainder of the model 13 mentioned above m, whether to reach the upper limit flag • remove itself cf55d • DFS (I, M, L, flag) • enumerate the number of I-bits, the previously mentioned model lcm (0 .. 9), lcm (The number mentioned above), whether to reach the upper limit • contains "49" • DFS (I, K, find, flag) • enumerates the I-th digit, whether the previous digit is K, whether it contains "49" (FIND), and whether it reaches the upper limit • Classification discussion: whether the previous digit is 4, and whether it currently contains "49"
Among these types, 49 is the most similar to Microsoft, but note that the prefix 0 needs to be removed during the operation, and eventuallyCodeAs follows:
# Include <iostream> # include <algorithm> # include <cstdlib> # include <cstring> using namespace STD; typedef long ll; # define MEM (A, B) memset (a, B, sizeof (A) const int L = 20, P = 1e9 + 7; struct res {ll all, sum, CNT; res () {} res (int I, Int J, int K): All (I), sum (J), CNT (k) {}} DP [l]; ll chkmod (ll x, ll p) {return (X % P + p) % P;} int d [L], n; Res DFS (INT POs, int up) {If (Pos <0) {return res (0, 0, 1) ;}if (! Up &&~ DP [POS]. All) {return DP [POS];} res RET (0, 0); int up = up? D [POS]: 9; ret. all + = DFS (pos-1, up & up = 0 ). all; ret. all % = P; For (INT I = 1; I <= up; I ++) {int NUP = up & I = up; for (Int J = pos-1; j> =-1; j --) {ll TMP = DFS (J, NUP ). sum + DFS (J, NUP ). CNT * (POS-1-j); TMP % = P; ret. all + = TMP; ret. all % = P; ret. sum + = TMP; ret. sum % = P; ret. CNT + = DFS (J, NUP ). CNT; ret. CNT % = P; NUP = NUP & D [J] = 0 ;//!!!}} If (! Up) {DP [POS] = ret;} return ret;} ll CAL (ll x) {n = 0; while (X) {d [n ++] = x % 10; X/= 10;} return DFS (n-1, 1 ). all;} int main () {MEM (DP,-1); ll n; while (CIN> N) {cout <CAL (n) <Endl ;} return 0 ;}