[CF628D]Magic Numbers 题解

比较友好的数位$dp$练手题。

设$dp(i,j,k=0/1)$表示还剩$i$位,前几位表示的数$\equiv\text{ j (mod m)}$,此位是否为偶数位的数的个数。

如果$k=0$,那么这一位一定不能是$d$。否则一定得是$d$。大力转移即可。
边界:$dp(0,0,0/1)=1$.

特别注意本题并不需要高精$+1$操作,只需要特判$b$一个数即可。

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/**
* @Author: Mingyu Li
* @Date: 2019-03-10T15:39:26+08:00
* @Email: class11limingyu@126.com
* @Filename: cf628D.cpp
* @Last modified by: Mingyu Li
* @Last modified time: 2019-03-10T20:44:04+08:00
*/

#include <bits/stdc++.h>
#define tpname typename
#define Go(i , x , y) for(register int i = x; i <= y; i++)
#define God(i , y , x) for(register int i = y; i >= x; i--)
typedef long long LL;
typedef long double ld;
typedef unsigned long long ULL;
template < tpname T > void sc(T& t) {
char c = getchar(); T x = 1; t = 0; while(!isdigit(c)) {if(c == '-') x = -1; c = getchar();}
while(isdigit(c)) t = t * 10 + c - '0' , c = getchar();t *= x;
}
template < tpname T , tpname... Args > void sc(T& t , Args&... args) {sc(t); sc(args...);}
template < tpname T > T mul(T x , T y , T _) {
x %= _,y %= _; return ((x * y - (T)(((ld)x * y + 0.5) / _) * _) % _ + _) % _;
}

const int N = 2000 + 5;
const int mod = (int)(1e9 + 7);
int m , D , p;
std::string a,b;
int d[2000];
// f[i][j][k]:
// 还剩i位 前几位组成的数%m = j 是否是偶数位

int dp[N][N][2];
int f(int i , int j ,int k) {
if(dp[i][j][k] != -1) return dp[i][j][k];
if(i == 0) return dp[i][j][k] = j%m == 0 ? 1 : 0;

int ans = 0;
Go(x , 0 , 9) {
if(k == 1 && x != D) continue;
if(k == 0 && x == D) continue;
ans = (ans + f(i-1 , (j*10 + x)%m , k^1)) % mod;
}
return dp[i][j][k] = ans;
}

int cal(std::string x) {
p = 0;
while(!x.empty()) {
d[p++] = x.back() - '0';
x.pop_back();
}

int op=0 , ans=0;
God(i , p-1 , 1) {
Go(j , 1 , 9) {
if(j == D) continue;
ans = (ans + f(i-1 , j%m , 1)) % mod;
}
}

op = 0; int lst = 0;
God(i , p-1 , 0) {
Go(j , (i == p-1) ? 1 : 0 , d[i] - 1) {
if(op == 1 && j != D) continue;
if(op == 0 && j == D) continue;
ans = (ans + f(i , (lst * 10 + j) % m , op^1)) % mod;
}
if(op == 1 && d[i] != D) break;
if(op == 0 && d[i] == D) break;
op = 1 - op;
lst = (lst * 10 + d[i]) % m;
}

return ans;
}
int main() {
memset(dp , -1 , sizeof(dp));
sc(m , D);
std::cin >> a >> b;
int ans = (cal(b) - cal(a) + mod) % mod;
bool f = 1 , op = 0;

int m1 = 0;
Go(i , 0 , (int)(b.size()) - 1) {
if(op == 0 && b[i]-'0'== D) f = 0;
if(op == 1 && b[i]-'0' != D) f = 0;
op = op^1;
}
for(char x : b) m1 = (m1 * 10 + x - '0')%m;
ans += (f & (m1 == 0));
ans %= mod;
std::cout << ans << std::endl;
return 0;
}

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×