AT_dp_s题解
这是一道比较板子的数位 dp 。
首先观察到 \(k\) 很大,肯定不能用枚举的方法求,然后就考虑用数位 dp 。对于这道题来说,我们可以在用记忆化搜索做数位 dp 的时候存一个当前各数位之和对 \(d\) 取余的余数,当把数填完之后判断余数是否为 \(0\) 就能判断这个数是否符合条件。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
inline int read(){
int f=1,w=0;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
w=(w<<1)+(w<<3)+(c^48);
c=getchar();
}
return f*w;
}
int a[10010];
char k[10100];
int d;
int tot;
int f[10100][110];
int dfs(int now,int res,int lim){
if(now>tot){
if(res) return 0;//若余数不为0说明这个数各数位之和无法被d整除,那么返回0
else return 1;
}
if(!lim&&f[now][res]!=-1) return f[now][res];//记忆化搜索实现数位dp
int mx;
if(lim){
mx=a[now];
}else{
mx=9;
}
int ans=0;
for(int i=0;i<=mx;i++){
(ans+=dfs(now+1,(res+i)%d,lim&(i==mx)))%=mod;
}
if(!lim) f[now][res]=ans;
return ans;
}
void init(){
for(int i=1;i<=tot;i++){
a[i]=k[i]-'0';
}
}
signed main(){
scanf("%s",k+1);
tot=strlen(k+1);
d=read();
init();
memset(f,-1,sizeof(f));
cout<<(dfs(1,0,1)-1+mod)%mod<<endl;
return 0;
}

浙公网安备 33010602011771号