[AHOI2009]同类分布【数位DP】

题目链接

  如果考虑成为数位dp的话,应该怎么做呢?

  dfs(数位,数位和,状态,是否为阈值);

  很明显,dfs是这样的,但是会发现,这样的状态记录会是很大的,无法用数组记录,此时,我们不妨枚举数位和,又有数位和==模值,最后的状态应该为0、且数位和==模值。所以dp方程显而易见。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <string>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <limits>
 8 #include <vector>
 9 #include <stack>
10 #include <queue>
11 #include <set>
12 #include <map>
13 #include <bitset>
14 #include <unordered_map>
15 #include <unordered_set>
16 #define lowbit(x) ( x&(-x) )
17 #define pi 3.141592653589793
18 #define e 2.718281828459045
19 #define INF 0x3f3f3f3f
20 #define HalF (l + r)>>1
21 #define lsn rt<<1
22 #define rsn rt<<1|1
23 #define Lson lsn, l, mid
24 #define Rson rsn, mid+1, r
25 #define QL Lson, ql, qr
26 #define QR Rson, ql, qr
27 #define myself rt, l, r
28 #define pii pair<int, int>
29 #define MP(a, b) make_pair(a, b)
30 using namespace std;
31 typedef unsigned long long ull;
32 typedef unsigned int uit;
33 typedef long long ll;
34 ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
35 const int maxN = 180;
36 ll A, B;
37 int dig[21];
38 ll mod;
39 ll dp[21][maxN][maxN];
40 ll dfs(int pos, int sum, int state, bool top)
41 {
42     if(sum > mod) return 0;
43     if(pos <= 1)
44     {
45         if(sum == mod && !state) return 1;
46         else return 0;
47     }
48     if(!top && (~dp[pos][sum][state])) return dp[pos][sum][state];
49     ll ans = 0;
50     int u = top ? dig[pos - 1] : 9;
51     for(int i = 0; i <= u; i ++)
52     {
53         ans += dfs(pos - 1, sum + i, (state * 10 + i) % mod, top && (i == u));
54     }
55     if(!top) dp[pos][sum][state] = ans;
56     return ans;
57 }
58 ll solve(ll x)
59 {
60     ll ans = 0;
61     for(int i = 1; i <= 20; i ++)
62     {
63         dig[i] = x % 10;
64         x /= 10;
65     }
66     for(int i = 1; i < maxN; i ++)
67     {
68         mod = i;
69         memset(dp, -1, sizeof(dp));
70         ans += dfs(20, 0, 0, true);
71     }
72     return ans;
73 }
74 int main()
75 {
76     scanf("%lld%lld", &A, &B); A--;
77     printf("%lld
", solve(B) - solve(A));
78     return 0;
79 }
原文地址:https://www.cnblogs.com/WuliWuliiii/p/14135783.html