题目大意:
给你一个m,k,然后输入一个正整数a,和正整数b,(a,b的长度小于等于2000),问a到b中有多少魔力数字,所谓魔力数字就是,从高位到低位,偶数位置的数都是k,奇数位的数不能是k,并且这些数能被m整除。
解题思路:
老思路,设dp[pos][sta] 为枚举到第pos位,当前数%m等于sta的答案个数
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll Mod = 1e9 + 7;
const int maxl = 2010;
ll dp[maxl][maxl], num[maxl];
char s1[maxl], s2[maxl];
int m, d, l1, l2, cnt;
ll dfs(int pos, int sta, bool limit) {
if (pos == cnt + 1) return (sta == 0);//平时pos==0为啥不可行???
if (!limit && dp[pos][sta] != -1) return dp[pos][sta];
int up = limit ? num[pos] : 9;
ll ans = 0;
for (int i = 0; i <= up; i++) {
if (pos % 2 == 0 && i != d) continue; // 如果是偶数位,那么不等于d则跳过
if (pos % 2 && i == d) continue;// 如果是奇数位,那么等于d也跳过
ans = (ans + dfs(pos + 1, (sta * 10 + i) % m, limit && i == num[pos])) % Mod;
}
if (!limit) dp[pos][sta] = ans % Mod;
return ans % Mod;
}
ll solve(char * s) {
memset(dp, -1, sizeof(dp));
int l = strlen(s); cnt = l;
for (int i = l - 1; i >= 0; i--) num[i + 1] = s[i] - '0';
return dfs(1, 0, true);
}
int main() {
scanf("%d%d", &m, &d);
scanf("%s%s", s1, s2);
l1 = strlen(s1), l2 = strlen(s2);
ll ans = (solve(s2) - solve(s1) + Mod) % Mod;
bool vis = true;
ll tmp = 0;
for (int i = 0; i < l1; i++) {//因为s1,被减掉了,如果s1符合条件则要加上1
tmp = (tmp * 10 + (s1[i] - '0')) % m;
if ((i + 1) % 2 == 0 && (s1[i] - '0') != d) {vis = false; break;}
if ((i + 1) % 2 && (s1[i] - '0') == d) {vis = false; break;}
}
if (vis && tmp % m == 0) ans += 1;//s1符合条件
printf("%lld\n", ans % Mod);
}
疑惑
为啥像平常那样划分不行
这题目有个bug,就是一位数都可以…