数位dp

https://vjudge.net/contest/237022#problem/E

题意:给出区间【A,B】,询问该区间中有多少数满足该数能整除其数位之和?

提示:数位dp状态为dp[pos][sum][mod][res],其中pos表示当前在第几位,sum表示当前的数位之和,mod表示模,res表示当前的构成的数%mod的值。

当pos为最后一位,且sum == mod && res == 0时,返回1;否则返回0;

其中,mod从1至81枚举,对于每个mod求一次dfs。

注意dp数组只用初始化一次,因为不同case中用到的dp数组是相同的,不然会超时。另外,数组尽量开刚刚好,否则会爆内存。

参考以下博客:https://blog.csdn.net/my_acm_dream/article/details/41910839

 1 //#include<bits/stdc++.h>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <string>
 7 #include <cmath>
 8 #include <cstdlib>
 9 #include <queue>
10 #include <stack>
11 #include <map>
12 #include <vector>
13 #include <set>
14 #include <bitset>
15 #include <iomanip>
16 #define ms(a, b) memset(a, b, sizeof(a));
17 using namespace std;
18 typedef long long LL;
19 typedef pair<int, int> pii;
20 const int INF = 0x3f3f3f3f;
21 const int maxn = 1e3 + 10;
22 const int MAXN = 2e4 + 10;
23 const double eps = 1e-8;
24 const int mod = 1e9 + 7;
25 int a, b;
26 int dp[11][82][82][82];
27 int bit[11];
28 
29 int dfs(int pos, int sum, int mod, int res, int f) {
30     if(pos < 1) return sum == mod && res == 0;
31     if(!f && dp[pos][sum][mod][res] != -1) return dp[pos][sum][mod][res];
32     int last = f ? bit[pos] : 9;
33     int ans = 0;
34     for(int i = 0; i <= last; i++) {
35         ans += dfs(pos-1, sum+i, mod, (res*10+i)%mod, f&&i==last);
36     }
37     if(!f) dp[pos][sum][mod][res] = ans;
38     return ans;
39 }
40 
41 int solve(int n) {
42     int len = 0;
43     while(n) {
44         bit[++len] = n % 10;
45         n /= 10;
46     }
47     int cnt = 0;
48     for(int i = 1; i <= 81; i++) {
49         cnt += dfs(len, 0, i, 0, 1);
50     }
51     return cnt;
52 }
53 
54 
55 int main() {
56 #ifdef local
57     freopen("case.in", "r", stdin);
58 //    freopen("case.out", "w", stdout);
59 #endif
60 //    ios::sync_with_stdio(false);
61 //    cin.tie(0);
62     int T;
63     scanf("%d", &T);
64     int kase = 0;
65     ms(dp, -1);
66     while(T--) {
67         scanf("%d%d", &a, &b);
68         int ans = solve(b) - solve(a-1);
69         printf("Case %d: %d\n", ++kase, ans);
70     }
71 //    solve();
72     return 0;
73 }

 

posted @ 2018-08-02 14:25  Sissi_hss  阅读(152)  评论(0编辑  收藏  举报