hdu3652 b-number 题解 题解: 代码:

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.

题意简述:求1-n中,含”13”且能被13整除的数的个数。

题解:

数位dp,记忆化搜索的时候记录一下当前的%13的余数,是否出现过13,。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#define REP(i, a, b) for(int i = a; i <= b; i ++)
#define REPG(i, x) for(int i = head[x]; i; i = g[i].nxt)
#define clr(x, y) memset(x, y, sizeof(x));
using namespace std;
typedef long long LL;
typedef double LF;
LL (LL a, LL b){return a > b ? a : b;}
LL Min(LL a, LL b){return a < b ? a : b;}
LL abs(LL x){return x > 0 ? x : -x;}
const int MAXN = 25;
int n, num[MAXN], f[MAXN][MAXN][MAXN];
inline int read(){
int r = 0, z = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') z = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){r = r * 10 + ch - '0'; ch = getchar();}
return r * z;
}
int dfs(int len, int mod, int typ, bool sx){
if(len == 0) return mod == 0 && typ == 2;
if(!sx && f[len][mod][typ] != -1) return f[len][mod][typ];
int maxx = sx ? num[len] : 9, mod_, typ_, sx_, cnt = 0;
for(int i = 0; i <= maxx; i ++){
mod_ = ((mod * 10) + i) % 13;
typ_ = typ;
if(typ == 0 && i == 1) typ_ = 1;
if(typ == 1 && i != 1) typ_ = 0;
if(typ == 1 && i == 3) typ_ = 2;
sx_ = (sx && i == maxx);
cnt += dfs(len - 1, mod_, typ_, sx_);
}
if(!sx) f[len][mod][typ] = cnt;
return cnt;
}
int solve(int x){
int k = 0;
while(x){num[++ k] = x % 10; x /= 10;}
return dfs(k, 0, 0, 1);
}
void work(){
while(~scanf("%d", &n)){
clr(f, -1);
printf("%dn", solve(n));
}
}
int main(){
work();
return 0;
}