Codeforces Beta Round #51 D. Beautiful numbers 数位DP

链接:

http://codeforces.com/contest/55/problem/D

题意:

定义Beautiful number,这个数能整除自己的每位数字

题解:

数位dp,所不同的是需要多加一维,因为需要记录下当前的数字,

dp[i][j][k]表示枚举到i位,当前数字为j(这里的j是%2520之后的),当前的最小公倍数为k

因为1-9的最小公倍数是2520,2520有48个因数,如果数组是ll dp[20][2520][2520]的话会超内存,所以对因子离散化一下就行了

代码:

31 ll a[20];
32 ll dp[20][2550][50];
33 int Hash[2550];
34 
35 ll gcd(ll a, ll b) {
36     return b == 0 ? a : gcd(b, a % b);
37 }
38 
39 ll lcm(ll a, ll b) {
40     return a / gcd(a, b) * b;
41 }
42 
43 ll dfs(int pos, int num, ll sta, bool limit) {
44     if (pos == -1) return num%sta == 0;
45     if (!limit && dp[pos][num][Hash[sta]] != -1) return dp[pos][num][Hash[sta]];
46     int up = limit ? a[pos] : 9;
47     ll res = 0;
48     rep(i, 0, up + 1) {
49         if (i == 0) res += dfs(pos - 1, (num * 10 + i) % 2520, sta, limit && i == a[pos]);
50         else res += dfs(pos - 1, (num * 10 + i) % 2520, lcm(sta, i), limit && i == a[pos]);
51     }
52     if (!limit) dp[pos][num][Hash[sta]] = res;
53     return res;
54 }
55 
56 ll solve(ll x) {
57     int pos = 0;
58     while (x) {
59         a[pos++] = x % 10;
60         x /= 10;
61     }
62     return dfs(pos - 1, 0, 1, true);
63 }
64 
65 int main() {
66     int cnt = 0;
67     rep(i, 1, 2521) if (2520 % i == 0) Hash[i] = cnt++;
68     int T;
69     cin >> T;
70     memset(dp, -1, sizeof(dp));
71     while (T--) {
72         ll l, r;
73         cin >> l >> r;
74         cout << solve(r) - solve(l - 1) << endl;
75     }
76     return 0;
77 }

 

posted @ 2017-05-23 10:20  Flowersea  阅读(191)  评论(0编辑  收藏  举报