比较友好的数位\(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\)一个数即可。
/** * @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; }转载于:https://www.cnblogs.com/LiM-817/p/10887225.html
相关资源:数据结构—成绩单生成器