-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy path1033(数位dp).cpp
77 lines (69 loc) · 1.79 KB
/
1033(数位dp).cpp
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define rep(a,b,c) for(int a = b ; a < c; a++)
const int mod = 1000000007;
struct node{
ll s,n;
};
node dp[21][20][400];
int bits[21];
ll base[21];
//len数位长度, dig是首个数字, begin_zero表示之前是否已经开始变号, end_flag表示下一位枚举时是否枚举到bit[len-2],否则就枚举到9, sum是要求的数字和
node dfs(int len, int dig, bool begin_zero, bool end_flag, int sum){
node t;
t.s = 0, t.n = 0;
//超过边界值
if(len <= 0 || len >= 20 || dig < 0 || dig > 9 || sum < -200 || sum >= 200)
return t;
//返回已有的DP结果,即记忆化搜索
if(!end_flag && dp[len][dig + (begin_zero?0:10)][sum+200].n != -1)
return dp[len][dig + (begin_zero?0:10)][sum+200];
//长度只有一位,就不需要枚举下一位了,直接讨论返回即可
if(len == 1){
if(dig != sum)
return t;
t.n = 1, t.s = sum;
return t;
}
//开始枚举下一位的数字
int end = end_flag? bits[len-2] : 9;
int newsum = dig - sum;
node tmp;
rep(j,0,end + 1){
if(!begin_zero){
tmp = dfs(len-1, j, j!=0, end_flag&& (j == end), sum);
}
else{
tmp = dfs(len-1, j, true, end_flag&& (j == end), newsum);
}
//将tmp的值累加到t上
t.n += tmp.n;
t.s = ((t.s + tmp.s)%mod + ((tmp.n * dig )%mod * base[len-1])%mod)%mod;
}
if(!end_flag) dp[len][dig + (begin_zero?0:10)][sum+200] = t;
return t;
}
int solve(ll n, int s){
if(n <= 0)
return 0;
int l = 0;
rep(i,0,21) bits[i] = 0;
while(n){
bits[l++]= n%10;
n /= 10;
}
return dfs(l+1,0,false,true,s).s;
}
int main(){
ll l, r, s;
node t;
t.n = -1;
t.s = 0;
rep(i,0,21) rep(j,0,20) rep(k,0,400) dp[i][j][k] = t;
base[0] = 1;
rep(i,1,21) base[i] = (base[i-1]*10)%mod;
cin >> l >> r >> s;
cout <<(solve(r,s) - solve(l-1,s) + mod )%mod << endl;
return 0;
}