[CF 628D] Magic Numbers

3 篇文章 0 订阅

题目

洛谷

题解

额,似乎是很板的一道数位 d p \tt dp dp

然而表示那个模 m m m 的余数,我有点懵 —— 如果是加一个第 2000 2000 2000 位上的数位,不就是 O ( 2000 ) O(2000) O(2000) 的判了吗?

然而我发现:从前往后填数不就没这个问题了吗?

写了一半天越写越乱……

Code:

LL d, m, Limit[MAXN], dp[MAXN][MAXN][2]; // dp[i][j] : 前 i 位模 m 为 j 的方案数, 下一维是 是否填满 
char l[MAXN], r[MAXN];
LL Dfs(LL Now,LL Get,LL End,bool NotMan)
{
	if (Now == End + 1)
		return ! Get;
	if (~ dp[Now][Get][NotMan])
		return dp[Now][Get][NotMan];
	LL All = 0;
	if (Now % 2)
	{
		for (Int i = (Now == 1 ? 1 : 0); i <= (NotMan ? 9 : Limit[Now]); ++ i)
			if (i != d)
				All += Dfs(Now + 1, (Get * 10 + i) % m, End, NotMan | (i != Limit[Now])), All %= Mod; 
	}
	else
	{
		if ( NotMan )
			All += Dfs(Now + 1, (Get * 10 + d) % m, End, NotMan), All %= Mod;
		else
		{
			if (Limit[Now] >= d)
				All += Dfs(Now + 1, (Get * 10 + d) % m, End, NotMan | (Limit[Now] != d)), All %= Mod;
		}
	}
	return dp[Now][Get][NotMan] = All;
}
inline LL Solve(char S[])
{
	LL Lens = strlen(S + 1);
	for (Int i = 1; i <= Lens; ++ i)
		Limit[i] = S[i] - '0';
	Dfs(1, 0, Lens, 0);
	return dp[1][0][0];
}
int main()
{
	memset(dp, -1, sizeof dp);
	read( m ); read( d );
	scanf("%s %s", l + 1, r + 1);
	LL Anss = Solve( r );
	memset(dp, -1, sizeof dp);
	Anss = ( Anss + Mod - Solve( l ) ) % Mod;
	LL Len = strlen(l + 1);
	bool Flag = 1;
	LL Get = 0;
	for (Int i = 1; i <= Len; ++ i)
	{
		Get = (Get * 10 + l[i] - '0') % m;
		if (i % 2)
		{
			if ((l[i] - '0') == d)
			{
				Flag = 0;
				break;
			}
		}
		else if ((l[i] - '0') != d)
		{
			Flag = 0;
			break;
		}
	}
	if (Get != 0)
		Flag = 0;
	if ( Flag )
		Anss = (Anss + 1 + Mod) % Mod;
	printf("%lld", Anss);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值