题意:定义d-magic数为d出现且只出现在偶数位上。问[l,r]内%m==0的d-magic数有多少个。
思路:一看便知是数位DP,还是很水的那种。。然而蒟蒻并不会。。
坑点:因为是大数,所以边界不能直接-1,可以用字符串模拟大数-1,也可以单独判断一下边界。
代码:
#include<bits/stdc++.h>
#define ll long long
#define pi acos(-1)
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define rep(i,x,n) for(int i=x;i<n;i++)
#define per(i,n,x) for(int i=n;i>=x;i--)
using namespace std;
typedef pair<int,int>P;
const int MAXN=100010;
const int mod=1e9+7;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int DP[2200][2200];
int DIG[2200];
int m,d,len;
int dfs(int pos,int pre,int limit)
{
if(pos == len)
return pre==0;
if(!limit && DP[pos][pre] != -1)
return DP[pos][pre];
int end = limit ? DIG[pos] : 9;
int ret = 0;
for(int i = 0;i <= end;i ++)
{
if((pos&1)&&i!=d)continue;
if((!(pos&1))&&i==d)continue;
ret += dfs(pos + 1,(pre*10+i)%m,limit && (i == end)),ret%=mod;
}
if(!limit)
DP[pos][pre] = ret;
return ret;
}
string l,r;
bool check()
{
int s=0;
for(int i=0;i<len;i++)
{
s=s*10+DIG[i];
s%=m;
if(DIG[i]==d&&(!(i&1)))return false;
if(DIG[i]!=d&&(i&1))return false;
}
return s==0;
}
int main()
{
ll ans;
std::ios::sync_with_stdio(0);
memset(DP,-1,sizeof(DP));
cin>>m>>d;
cin>>l>>r;
len=l.size();
for(int i=0;i<len;i++)
DIG[i]=l[i]-'0';
ans=dfs(0,0,1);
ans-=check();
len=r.size();
for(int i=0;i<len;i++)
DIG[i]=r[i]-'0';
cout<<(dfs(0,0,1)-ans+mod)%mod;
return 0;
}