题目
题解
额,似乎是很板的一道数位 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;
}