数位$dp$
这里我们首先考虑一种做法,就是记录$f[pos][sum][num]$表示当前是第$pos$位,总的数字和为$sum$,现在的数字是$num$,那么我们看看下面一行小字,输入的数位数小于等于$1000$,????一脸懵逼,开个么大的$f$数组??
于是我们优化一下,我们枚举各位数之和为模数就行了,具体看代码:
#include<iostream> #include<cstdio> #include<cstring> #define ll long long #define N 21 using namespace std; int val[N]; ll l,r,mod; ll f[N][207][207]; ll Dfs(int pos,ll sum,ll num,bool limit,bool lead) { if(!pos&!sum) return 0; if(!pos) { if(sum==mod&&!num) return 1; else return 0; } if(!limit&&!lead&&f[pos][sum][num]!=-1) return f[pos][sum][num]; int maxn=limit?val[pos]:9; ll ans=0; for(int i=0;i<=maxn;++i) ans+=Dfs(pos-1,sum+i,(num*10+i)%mod,limit&&(i==maxn),(lead&&!i)); if(!limit&&!lead) f[pos][sum][num]=ans; return ans; } ll Get(ll x) { int len=0; while(x) { val[++len]=x%10; x/=10; } ll ans=0; for(mod=1;mod<=9*len;++mod) { memset(f,-1,sizeof(f)); ans+=Dfs(len,0,0,1,1); } return ans; } int main() { //memset(f,-1,sizeof(f)); scanf("%lld%lld",&l,&r); printf("%lld",Get(r)-Get(l-1)); return 0; }