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号