Magic Numbers
题解
还是一道很常规的数位dp。
由于,还是需要特判一下的值,差分求答案。
令为到第位,之前各数位和在模的意义下为时的方案数。由于要求的数偶数位为奇数位不为,在搜索的过程中需要特判一下,最后统计第二位为0时的值。
dp的过程可以通过记忆化搜索来实现,转移方程也很好想。
源码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const LL mo=1e9+7;
LL m,d,ans,bit[2005],dp[2005][2005],len;
char l[2005],r[2005];
LL dfs(int pos,LL sum,bool flag){
if(pos==-1)return sum==0;LL res=0;
if(!flag&&dp[pos][sum]>=0)return dp[pos][sum];
for(int i=0,lim=flag?bit[pos]:9;i<=lim;i++){
if(((len-pos)&1)==(i==d))continue;
(res+=dfs(pos-1,(sum*10ll+i)%m,flag&&(i==lim)))%=mo;
}
return flag?res:dp[pos][sum]=res;
}
LL calc(char *str){
len=(int)strlen(str);
for(int i=0;i<len;i++)bit[len-i-1]=str[i]-'0';
return dfs(len-1,0,1);
}
LL check(){
LL sum=0;len=(int)strlen(l);
for(int i=0;i<len;i++){
int x=l[i]-'0';
if((i&1)==(x!=d))return 0;
sum=(sum*10ll+x)%m;
}
return !sum;
}
signed main(){
memset(dp,-1,sizeof(dp));
scanf("%lld %lld",&m,&d);
scanf("%s\n%s",l,r);
ans=calc(r)-calc(l)+check();
printf("%lld\n",(ans%mo+mo)%mo);
return 0;
}