Hdu 3652 B-number (Digital dp)
Http://acm.hdu.edu.cn/showproblem.php? Pid = 1, 3652
General question: "B-number" indicates that an integer contains a substring "13" and is divisible by 13. Calculate the number of such numbers between 1-n.
Train of Thought: There are two restrictions: the sub-string "13" can be divisible by 13. Set "dp [site] [mod] [flag]" to the number of places where the remainder of the 13 th site pair is mod and flag. Flag indicates whether the Sub-string "13" is contained ". Then, search for memory words.
# Include <stdio. h> # include <iostream> # include <map> # include <stack> # include <vector> # include <math. h> # include <string. h> # include <queue> # include <string> # include <stdlib. h >#include <algorithm> # define LL long # define _ LL _ int64 # define eps 1e-8 # define PI acos (-1.0) using namespace std; int dp [15] [15] [5]; int dig [15]; // flag = 0 indicates that the previous one is not 1, flag = 1 indicates that the previous one is 1, flag = 2 indicates that "13" appears ". Int dfs (int site, int mod, int flag, int up) {if (site = 0) return mod = 0 & flag = 2; // when mod is 0 and "13" exists, 1 if (! Up & dp [site] [mod] [flag]! =-1) // memorized return dp [site] [mod] [flag]; int len = up? Dig [site]: 9; int ans = 0; for (int I = 0; I <= len; I ++) {int tmod = (mod * 10 + I) % 13; int tflag = flag; if (flag = 1 & I = 3) tflag = 2; else if (flag = 0 & I = 1) tflag = 1; else if (flag = 1 & I! = 1) tflag = 0; ans + = dfs (site-1, tmod, tflag, up & (I = len);} if (! Up) dp [site] [mod] [flag] = ans; return ans;} int cal (int n) {int cnt = 0; while (n) {dig [++ cnt] = n % 10; n/= 10;} memset (dp,-1, sizeof (dp); return dfs (cnt, 0, 0, 1);} int main () {int n; while (~ Scanf ("% d", & n) {printf ("% d \ n", cal (n) ;}return 0 ;}