hdu3652(数位dp,记忆化搜索)
题目描述:
B-number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 12235 Accepted Submission(s): 7320 Problem Description A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- string "13" and can be divided by 13. For example, 130 and 2613 are wqb-numbers,
but 143 and 2639 are not. Your task is to calculate how many wqb-numbers from 1 to n for a given integer n. Input Process till EOF. In each line, there is one positive integer n(1 <= n <= 1000000000). Output Print each answer in a single line. Sample Input 13 100 200 1000 Sample Output 1 1 2 2
思路:记忆化搜索
#include<iostream> #include<string.h> #include<cmath> #include<set> #include<map> #include<string> #include<queue> #include<stack> #include<vector> #include<bitset> using namespace std; typedef long long ll; inline ll read() { ll sum = 0, f = 1; char p = getchar(); for (; !isdigit(p); p = getchar()) if (p == '-')f = -1; for (; isdigit(p); p = getchar()) sum = sum * 10 + p - 48; return sum * f; } const int maxn = 50; int n,dig[maxn],len,res; int dp[maxn][13][3]; int dfs(int len, int ismax,int last,int has13) { int ans = 0, maxx,has,pre,lastx; if (!len)return last == 0 && has13==2; if (!ismax&&dp[len][last][has13] != -1)return dp[len][last][has13]; maxx = ismax ? dig[len] : 9; for (int i = 0; i <= maxx; i++) { lastx = (last * 10 + i) % 13; if (has13 == 2)has = 2; else if (has13 == 1 && i == 3)has = 2; else if (i == 1)has = 1; else has = 0; ans += dfs(len - 1, ismax && i == maxx, lastx,has); } if (!ismax)dp[len][last][has13] = ans; return ans; } int main() { //freopen("test.txt", "r", stdin); while (~scanf("%d", &n)) { res = len = 0; memset(dp, -1, sizeof(dp)); while (n){ dig[++len] = n % 10; n /= 10; }dig[len + 1] = 0; printf("%d\n", dfs(len, 1, 0, 0)); } return 0; }