题目描述
给出两个数a,b,求出[a,b]中各位数字之和能整除原数的数的个数。
输入格式
一行,两个整数a和b
输出格式
一个整数,表示答案
输入输出样例
输入 #1
10 19
输出 #1
3
说明/提示
对于所有的数据,1≤a≤b≤10^18
记录pos,sum(数字各位上的数的和),st(原数),limit
这里st可达到1e18显然是不能作为dp转移的下标直接记录的
所以我们考虑取模
我们最理想的模数当然是把每次搜到最后得到的数字各个位数之和
但是我们发现在这个过程中sum是发生变化的
所以我们就应该以一个定值作为模数
那好,我们虽然不知道最后各位之和的结果,我们枚举总可以吧
我们只需要枚举所有的各位数字之和作为模数
最后判断sum和枚举的mod相等并且st%sum=0的数就是符合题意的答案
#include<bits/stdc++.h>
using namespace std;
#define int long long
int l,r;
int len,mod;
int dp[20][200][200],a[20];
int dfs(int pos,int sum,int st,int limit)
{
if(pos==0&&sum==0) return 0;
if(pos==0) return st==0&&sum==mod?1:0;
if(!limit&&dp[pos][sum][st]!=-1) return dp[pos][sum][st];
int res=0, up=limit ? a[pos] : 9;
for(int i=0; i<=up; i++)
res+=dfs(pos-1,sum+i,(10ll*st+i)%mod, limit&&i==up);
return limit?res:dp[pos][sum][st]=res;
}
int cal(int x)
{
len=0;
while (x) a[++len]=x%10,x/=10;
int ret=0;
for(mod=1; mod<=9*len; mod++)
{
memset(dp,-1,sizeof dp);
ret+=dfs(len,0,0,1);
}
return ret;
}
signed main()
{
cin>>l>>r;
cout<<cal(r)-cal(l-1)<<"\n";
return 0;
}