codeforces 628D. Magic Numbers 数位dp
给两个数m, d. 两个数a, b。 a, b长度小于2000, 长度相等。求在a, b之间的数x, x%m==0, 并且从高位往低位数, 奇数位的数全部不等于d, 偶数为的数全都等于d, 求这样的数的个数。
数位dp, 通常的都是从后往前dfs, 但是这个题因为有第二个条件, 所以应该从前往后dfs, 具体的dfs过程看代码。
#include <iostream> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <set> #include <string> #include <queue> #include <stack> #include <bitset> using namespace std; #define pb(x) push_back(x) #define ll long long #define mk(x, y) make_pair(x, y) #define lson l, m, rt<<1 #define mem(a) memset(a, 0, sizeof(a)) #define rson m+1, r, rt<<1|1 #define mem1(a) memset(a, -1, sizeof(a)) #define mem2(a) memset(a, 0x3f, sizeof(a)) #define rep(i, n, a) for(int i = a; i<n; i++) #define fi first #define se second typedef pair<int, int> pll; const double PI = acos(-1.0); const double eps = 1e-8; const int mod = 1e9+7; const int inf = 1061109567; const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; int m, d, len; char s[2005]; ll dp[2005][2005]; ll dfs(int pos, int md, int fp) { if(pos == len+1) { return md == 0; } if(~dp[pos][md]&&!fp) { return dp[pos][md]; } int ed = fp?s[pos]-'0':9; ll ret = 0; for(int i = 0; i<=ed; i++) { if(pos%2&&i==d) continue; if(pos%2==0&&i!=d) continue; ret = (ret + dfs(pos+1, (md*10+i)%m, fp&&i == ed))%mod; } return fp?ret:dp[pos][md] = ret; } int main() { mem1(dp); cin>>m>>d; scanf("%s", s+1); len = strlen(s+1); int tmp = 0, flag = 0; for(int i = 1; i<=len; i++) { tmp = tmp*10+s[i]-'0'; tmp %= m; if(i%2&&s[i]-'0' == d) flag = 1; if(i%2==0&&s[i]-'0'!=d) flag = 1; } if(tmp!=0) flag = 1; ll ans1 = dfs(1, 0, 1); if(!flag) ans1--; scanf("%s", s+1); ll ans2 = dfs(1, 0, 1); cout<<(ans2-ans1+mod)%mod; return 0; }