CodeForces 628D Magic Numbers(数位DP)

题意:如果一个数转化成十进制后奇数位上全不为d,偶数位上全为d,那么就称这个数为d魔力数,现在问区间[a,b]内有多少个被m整除的d魔力数。

思路:比较典型的数位DP,先求出[1,b]之间的魔力数再减去[1,a]之间的魔力数,如果a也是一个魔力数那么还要加一。

在求[1,a]这个区间内的魔力数时,dfs(len, mod, same)这三个参数分别表示 当前位,当前的余数,是否和a具有相同的前缀,然后记忆化搜索就可以了。

#include<bits/stdc++.h>
#define eps 1e-6
#define LL long long
#define pii pair<int, int>
#define pb push_back
#define mp make_pair
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

const int MOD = 1e9+7;
int m, d, len;
char a[3000], b[3000];
LL dp[2500][2500];

LL dfs(int pos, int mod, bool same, char* s)
{
	if (!same && (dp[pos][mod] != -1)) 
		return dp[pos][mod];
	if (pos > len) 
		return mod==0;
	int maxd = same ? s[pos]-'0' : 9;
	LL ans = 0;
	for (int i = 0; i <= maxd; i++) {
		if (((pos&1)&&(i == d)) || !(pos&1)&&(i != d) )
			continue;
		ans = (ans + dfs(pos+1, (mod*10+i)%m, same && (i == maxd), s)) % MOD;
	}
	if (!same) 
		dp[pos][mod] = ans;
	return ans;
}

int judge(char *s) 
{
	int cnt = 0, mod = 0;
	for (int i = 1; i <= len; i++)
	{
		mod = (mod*10 + s[i]-'0') % m;
		if (((i&1) && (s[i]-'0' == d)) || (!(i&1) && (s[i]-'0' != d)))
			return 0;
	}
	return mod==0;
}

int main()
{
    //freopen("input.txt", "r", stdin);
	cin >> m >> d >> a+1 >> b+1;
	len = strlen(a+1);
	memset(dp, -1, sizeof(dp));
	LL ans = dfs(1, 0, 1, b);
	memset(dp, -1, sizeof(dp));
	ans = ((ans - dfs(1, 0, 1, a)) % MOD + MOD) % MOD;
	cout << ans+judge(a);
    return 0;
}

















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值