D. Magic Numbers
题意:明显数位dp,但是关键怎么写。
题解:直接看代码,更加清晰。这个dp方程我其实想到了,但是还是不够熟练地写出来。第一维是数位,第二维是mode m 的余数 , 第三维是当前数位限制。排除不合法的方案(continue掉的)。
ok函数就是检验b是否是个有效解。因为减答案的时候将b减掉了。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod = 1e9+7;
int dp[2020][2020][2],n;
string x1,x2;
int b[3000];
int m,d;
ll dfs(int pos,int mo,int lim)
{
if(pos==n+1) return (mo==0);
if(dp[pos][mo][lim]!=-1) return dp[pos][mo][lim];
int up = (lim==1)? b[pos] : 9;
ll ans = 0;
for(int i=0;i<=up;i++)
{
if(pos%2==0&&i!=d) continue;
if(pos%2&&i==d) continue;
int mo2 = (mo*10+i) % m;
ans = ( ans% mod + dfs(pos+1,mo2,lim&&i==up) % mod ) % mod;
}
return dp[pos][mo][lim] = ans;
}
bool ok()
{
int len = x1.length();
int flag = 0,mo = 0;
for(int i=0;i<len;i++)
{
if((i+1)%2==0&&b[i+1]!=d) {flag =1;break;}
if((i+1)%2 && b[i+1]==d) {flag =1;break;}
mo = (mo*10+b[i+1]) % m;
}
return (!flag)&&(mo==0);
}
int main()
{
memset(dp,-1,sizeof(dp));cin>>m>>d;
cin>>x1>>x2;
n = x2.length();
for(int i=0;i<n;i++) b[i+1] = x2[i] - '0';
ll ans = 0;
ans = dfs(1,0,1);
n = x1.length();
for(int i=0;i<n;i++) b[i+1] = x1[i] - '0';
memset(dp,-1,sizeof(dp));
if(ok()) ans ++;
ans = ( ans - dfs(1,0,1) + mod ) % mod;
cout<<ans<<endl;
}