数位$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;
}