CF628 D. Magic Numbers

题目大意:

给你一个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,就是一位数都可以…

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值