.
题意:给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数。
题解:数位DP
$f[i][j][k][l]$表示前$i$位,数字和为$j$,模$i=k$,是否贴着上界。枚举数字和,然后就可以转移了。具体看代码。注意暴力推会超时,要加点小优化。
代码:
#include<bits/stdc++.h>
using namespace std;
long long a,b,f[20][180][180][2];
char s[20];
int len;
long long dp(int mod)
{
memset(f,0,sizeof(f));
for(int i=0;i<=s[0]-'0';i++)
f[0][i][i%mod][i==s[0]-'0']=1;
for(int i=0;i<len-1;i++)
for(int j=0;j<=mod;j++)
for(int k=0;k<mod;k++)
for(int l=0;l<2;l++)
{
if(!f[i][j][k][l])
continue;
int lim=l?s[i+1]-'0':9;
for(int o=0;o<=lim&&j+o<=mod;o++)
{
f[i+1][j+o][(k*10+o)%mod][l&&o==s[i+1]-'0']+=f[i][j][k][l];
}
}
return f[len-1][mod][0][0]+f[len-1][mod][0][1];
}
long long get(long long x)
{
if(x==0)
return 0;
long long ans=0;
memset(s,0,sizeof(s));
sprintf(s,"%lld",x);
len=strlen(s);
for(int i=1;i<=162;i++)
ans+=dp(i);
return ans;
}
int main()
{
scanf("%lld%lld",&a,&b);
int hh=0;
if(b==1000000000000000000LL)
{
hh=1;
b--;
}
printf("%lld",hh+get(b)-get(a-1));
}