一、题目
本题翻译有误,刚拿到这道题的同学一定要去看讨论区!
二、解法
能一眼看出来要写数位 d p dp dp吧,偶数位奇数位比较好处理,关键是判断能被 m m m整除,一个经典的讨论是转化成取模 m m m等于 0 0 0,设 d p [ i ] [ j ] dp[i][j] dp[i][j]未考虑到了第 i i i位,余数为 r r r的方案数,最后要求余数 = 0 =0 =0即可。
由于我们做了差分,注意要特判 l l l是不是满足要求的数。
#include <cstdio>
#include <cstring>
#define int long long
const int M = 2005;
const int MOD = 1e9+7;
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,m,d,l,r,a[M],dp[M][M];char s[M];
int dfs(int x,int r,int up,int zero)
{
if(!x) return !r && !zero;
if(dp[x][r]!=-1 && !up && !zero) return dp[x][r];
int ans=0;
for(int i=0;i<=9;i++)
{
if(up && i>a[x]) break;
if(((n-x)%2==1 && i!=d) || ((n-x)%2==0 && i==d))
continue;
ans=(ans+dfs(x-1,(10*r+i)%m,up&&(i==a[x]),zero&&(i==0)))%MOD;
}
if(!up && !zero) dp[x][r]=ans;
return ans;
}
int work(int f)
{
scanf("%s",s);n=strlen(s);
for(int i=0;i<n;i++)
a[n-i]=s[i]-'0';
int sum=0;
for(int i=0;i<n;i++)
{
int x=s[i]-'0';
if((i+1)&1) {if(x==d) f=1;}
else {if(x!=d) f=1;}
sum=(sum*10+x)%m;
}
return dfs(n,0,1,1)-(sum==0 && f==0);
}
signed main()
{
memset(dp,-1,sizeof dp);
m=read();d=read();
int l=work(0),r=work(1);
printf("%lld\n",(r-l+MOD)%MOD);
}